C: Где практически используется соединение?

not необходимо поместить реализацию в файл заголовка, см. альтернативное решение в конце этого ответа.

В любом случае причина, по которой ваш код не работает, что при создании экземпляра шаблона компилятор создает новый класс с заданным аргументом шаблона. Например:

template
struct Foo
{
    T bar;
    void doSomething(T param) {/* do stuff using T */}
};

// somewhere in a .cpp
Foo f; 

При чтении этой строки компилятор создаст новый класс (назовем его FooInt), что эквивалентно следующему:

struct FooInt
{
    int bar;
    void doSomething(int param) {/* do stuff using int */}
}

Следовательно, компилятор должен иметь доступ к реализации методов, чтобы создать экземпляр с аргументом шаблона (в данном случае int). Если эти реализации не были в заголовке, они не были бы доступны, поэтому компилятор не смог бы создать экземпляр шаблона.

Общим решением для этого является запись объявления шаблона в заголовок файла, затем реализовать класс в файле реализации (например, .tpp) и включить этот файл реализации в конец заголовка.

// Foo.h
template 
struct Foo
{
    void doSomething(T param);
};

#include "Foo.tpp"

// Foo.tpp
template 
void Foo::doSomething(T param)
{
    //implementation
}

Таким образом, реализация по-прежнему отделена от объявления, но доступен компилятору.

Другое решение состоит в том, чтобы сохранить реализацию отдельно и явно создать все экземпляры шаблона, которые вам понадобятся:

// Foo.h

// no implementation
template  struct Foo { ... };

//----------------------------------------    
// Foo.cpp

// implementation of Foo's methods

// explicit instantiations
template class Foo;
template class Foo;
// You will only be able to use Foo with int or float

Если мое объяснение isn ' t достаточно ясно, вы можете взглянуть на C ++ Super-FAQ по этому вопросу .

30
задан timrau 14 August 2012 в 23:57
поделиться

17 ответов

Я обычно использую союзы при разборе текста. Я использую нечто подобное:

typedef enum DataType { INTEGER, FLOAT_POINT, STRING } DataType ;

typedef union DataValue
{
    int v_int;
    float v_float;
    char* v_string;
}DataValue;

typedef struct DataNode
{
    DataType type;
    DataValue value;
}DataNode;

void myfunct()
{
    long long temp;
    DataNode inputData;

    inputData.type= read_some_input(&temp);

    switch(inputData.type)
    {
        case INTEGER: inputData.value.v_int = (int)temp; break;
        case FLOAT_POINT: inputData.value.v_float = (float)temp; break;
        case STRING: inputData.value.v_string = (char*)temp; break;
    }
}

void printDataNode(DataNode* ptr)
{
   printf("I am a ");
   switch(ptr->type){
       case INTEGER: printf("Integer with value %d", ptr->value.v_int); break;
       case FLOAT_POINT: printf("Float with value %f", ptr->value.v_float); break;
       case STRING: printf("String with value %s", ptr->value.v_string); break;
   }
}

Если вы хотите посмотреть, как используются союзы ЗДЕСЬ, проверьте любой код, используя flex/bison. Например, см. splint, он содержит ТОНЫ союзов.

.
33
ответ дан 27 November 2019 в 23:45
поделиться

Союзы полезны, если у вас разные типы сообщений, и в этом случае вам не обязательно знать на каких-то промежуточных уровнях точный тип. Только отправитель и получатель должны разобрать фактическое сообщение сообщения. Любые другие уровни действительно должны знать только размер и, возможно, информацию об отправителе и/или получателе.

.
2
ответ дан 27 November 2019 в 23:45
поделиться

Унионы также могут быть полезны, когда тип перфорации, что желательно в некоторых избранных местах (например, некоторые методы для сравнения с плавающей точкой алгоритмов).

.
0
ответ дан 27 November 2019 в 23:45
поделиться

Для удобства я использую союзы, чтобы использовать тот же класс для хранения значений xyzw и rgba

#ifndef VERTEX4DH
    #define VERTEX4DH

    struct Vertex4d{

        union {
            double x;
            double r;
        };
        union {
            double y;
            double g;
        };
        union {
            double z;
            double b;
        };
        union {
            double w;
            double a;
        };

        Vertex4d(double x=0, double y=0,double z=0,double w=0) : x(x), y(y),z(z),w(w){}
    };

#endif
0
ответ дан 27 November 2019 в 23:45
поделиться

Многие примеры союзов можно найти в . Немногие другие находятся в некоторых IP-стеках (например, в BSD ).

Как правило, реализации протоколов используют союзную конструкцию.

.
0
ответ дан 27 November 2019 в 23:45
поделиться

Другой пример больше: чтобы сэкономить на выполнении кастингов.

typedef union {
  long int_v;
  float float_v;
} int_float;

void foo(float v) {
  int_float i;
  i.float_v = v;
  printf("sign=%d exp=%d fraction=%d", (i.int_v>>31)&1, ((i.int_v>>22)&0xff)-128, i.int_v&((1<<22)-1));
}

вместо:

void foo(float v) {
  long i = *((long*)&v);
  printf("sign=%d exp=%d fraction=%d", (i>>31)&1, ((i>>22)&0xff)-128, i&((1<<22)-1));
}
0
ответ дан 27 November 2019 в 23:45
поделиться

Пример:

При использовании различных типов сокетов, но вы хотите, чтобы на них ссылался тип comon.

.
0
ответ дан 27 November 2019 в 23:45
поделиться

Вы имеете в виду что-то подобное ?

union {
   long long a;
   unsigned char b[sizeof(long long)];
} long_long_to_single_bytes;

ADDED:

Я недавно использовал это на нашей машине AIX для преобразования 64-битного машиноиндентификатора в байт-массив.

std::string getHardwareUUID(void) {
#ifdef AIX
   struct xutsname m; // aix specific struct to hold the 64bit machine id
   unamex(&b);        // aix specific call to get the 64bit machine id
   long_long_to_single_bytes.a = m.longnid;
   return convertToHexString(long_long_to_single_bytes.b, sizeof(long long));
#else // Windows or Linux or Solaris or ...
   ... get a 6byte ethernet MAC address somehow and put it into mac_buf
   return convertToHexString(mac_buf, 6);
#endif
1
ответ дан 27 November 2019 в 23:45
поделиться

Иногда я использовал объединения таким образом

//Define type of structure
typedef enum { ANALOG, BOOLEAN, UNKNOWN } typeValue_t;
//Define the union
typedef struct  {
  typeValue_t typeValue;
  /*On this structure you will access the correct type of
    data according to its type*/
  union {
    float ParamAnalog;
    char  ParamBool;
  };
} Value_t;

Тогда можно было объявить массивы с разными значениями, более или менее эффективно хранящие данные, и выполнить некоторые "полиморфные" операции типа:

 void printValue ( Value_t value ) {
    switch (value.typeValue) {
       case BOOL:
          printf("Bolean: %c\n", value.ParamBool?'T':'F');
          break;
       case ANALOG:
          printf("Analog: %f\n", value.ParamAnalog);
          break;
       case UNKNOWN:
          printf("Error, value UNKNOWN\n");
          break;
    }
 }
1
ответ дан 27 November 2019 в 23:45
поделиться
struct cat_info
{
int legs;
int tailLen;
};

struct fish_info
{
bool hasSpikes;
};


union 
{
fish_info fish;
cat_info cat;
} animal_data;

struct animal
{
char* name;
int animal_type;
animal_data data;
};
2
ответ дан 27 November 2019 в 23:45
поделиться

В мире Windows объединения обычно используются для реализации вариантов с метками , которые являются (или были до .NET?) одним из стандартных способов передачи данных между COM объектами.

Идея заключается в том, что тип объединения может обеспечить единый естественный интерфейс для передачи произвольных данных между двумя объектами. Некоторые COM объекты могут передавать вам вариант (например, тип VARIANT или _variant_t), который может содержать либо double, либо float, либо int, либо что угодно.

Если вам приходится иметь дело с COM объектами в коде Windows C++, то вы увидите типы вариантов повсюду.

3
ответ дан 27 November 2019 в 23:45
поделиться

Для пошагового и битового доступа к регистрам или портам ввода/вывода путём отображения этого конкретного порта в память, смотрите пример ниже:

    typedef Union
{
  unsigned int a;
struct {
  unsigned bit0 : 1,
           bit1 : 1,
           bit2 : 1,
           bit3 : 1,
           bit4 : 1,
           bit5 : 1,
           bit6 : 1,
           bit7 : 1,
           bit8 : 1,
           bit9 : 1,
           bit10 : 1,
           bit11 : 1,
           bit12 : 1,
           bit13 : 1,
           bit14 : 1,
           bit15 : 1
} bits;
} IOREG;

# define PORTA (*(IOREG *) 0x3B)
...
unsigned int i = PORTA.a;//read bytewise
int j = PORTA.bits.bit0;//read bitwise
...
PORTA.bits.bit0 = 1;//write operation
5
ответ дан 27 November 2019 в 23:45
поделиться

Я обычно использовал союзы, где вы хотите иметь различные представления о данных. Например, 32-битное значение цвета, где вы хотите и 32-битный val, и красный, зеленый, синий и альфа компоненты

struct rgba
{
  unsigned char r;
  unsigned char g;
  unsigned char b;
  unsigned char a;
};

union  
{
  unsigned int val;
  rgba components;
}colorval32;

NB То же самое вы могли бы достичь и с помощью битовой маскировки и сдвига, т.е.

#define GETR(val) ((val&0xFF000000) >> 24)

, но я считаю союзный подход более элегантным

.
6
ответ дан 27 November 2019 в 23:45
поделиться

Вот еще один пример, где объединение могло бы быть полезным.

(не моя собственная идея, я нашел это в документе, где обсуждается c++ optimizations)

begin-quote

.... Для экономии места можно использовать союзы, например,

сначала несоюзный подход:

void F3(bool useInt) {
    if (y) {
        int a[1000];
        F1(a);  // call a function which expects an array of int as parameter
    }
    else {
        float b[1000];
        F2(b);  // call a function which expects an array of float as parameter
    }
}

Здесь можно использовать одну и ту же область памяти для a и b, так как их живые диапазоны делают а не накладываться друг на друга. Вы можете сэкономить много кэш-памяти , присоединившись к a и b в союзе:

void F3(bool useInt) {

    union {
        int a[1000];
        float b[1000];
    };

    if (y) {
        F1(a);  // call a function which expects an array of int as parameter
    }
    else {
        F2(b);  // call a function which expects an array of float as parameter
    }
}

Использование союза не является безопасной практикой программирования, конечно, потому что вы получите не предупреждение компилятора, если использование a и b пересекаются. Следует использовать только этот метод для больших объектов, которые занимают много места в кэше. ...

endqoute

1
ответ дан 27 November 2019 в 23:45
поделиться
  • При чтении сериализованных данных, которые необходимо принудительно разделить на определенные типы.
  • При возврате семантических значений из lex в yacc. (yylval)
  • При реализации полиморфного типа, особенно такого, который читает DSL или общий язык
  • При реализации диспетчера, который специально вызывает функции, предназначенные для принятия различных типов.
1
ответ дан 27 November 2019 в 23:45
поделиться

Недавно я думаю, что видел какой-то союз, используемый в векторных программирования . Векторное программирование используется в технологии INTEL MMX Technology , оборудование GPU, English IBM широкополосный двигатель и другие.

Вектор может соответствовать 128-битному регистре. Это очень часто используется для архитектуры Simd . Поскольку оборудование имеет 128-битные регистры, вы можете хранить 4 одноточных точками в регистре / переменной. Простой способ построить, преобразовывать, экстракт отдельных элементов вектора - использовать объединение.

typedef union {
    vector4f vec; // processor-specific built-in type
    struct { // human-friendly access for transformations, etc
        float x;
        float y;
        float z;
        float w;
    };
    struct { // human-friendly access for color processing, lighting, etc
        float r;
        float g;
        float b;
        float a;
    };
    float arr[4]; // yet another convenience access
} Vector4f;

int main()
{
    Vector4f position, normal, color;
    // human-friendly access
    position.x = 12.3f;
    position.y = 2.f;
    position.z = 3.f;
    position.w = 1.f;

    // computer friendly access
    //some_processor_specific_operation(position.vec,normal.vec,color.vec);
    return 0;
}

Если вы возьмете путь в PlayStation 3 многоядерных программирования или графическому программированию, хороший шанс вы столкнетесь с большим количеством этих материалов.

1
ответ дан 27 November 2019 в 23:45
поделиться

SDL использует союз для представления событий: http://www.libsdl.org/cgi/docwiki.cgi/sdl_event .

2
ответ дан 27 November 2019 в 23:45
поделиться