2016-08-01 6 views
5

На работе я использовал linux и компилятор GCC для C++ 11 и C++ 14. В некоторых из кода на работе, я использовал союз, чтобы хранить как ссылки и указатель, как это: (Упростить до только важные части)Использование Союза со ссылкой

struct MyStruct 
{ 
    //Stuff 
    union { double& x; double* x_ptr; }; 
    MyStruct(double& value) : x(value) {} 
    //More stuff 
}; 

Я считаю, что этот код понятен, читаемым, однозначно и обеспечивает удобный способ хранения ссылок, которые могут быть перенесены на другое. Он обеспечивает легко понятный синтаксический сахар без рентабельности при улучшении читаемости. Однако, когда я попытался использовать такой код в visual studio 15, код не удалось скомпилировать из-за «незаконного члена объединения типа double &».

  1. Является ли этот код незаконным по стандарту или только под Visual Studio 2015?
  2. Могу ли я скомпилировать его в Visual Studio 2015 или отправить отчет об ошибке/запрос на изменение?
  3. Является ли использование союза таким образом плохой практикой?

Примечание: В моей работе почти весь код написан для Linux и скомпилирован с помощью GCC, а для моего конкретного проекта - C++ 11, и GCC является единственным компилятором, который будет использоваться.

Редактировать: Пожалуйста, не говорите мне, что помещение ссылки внутри союза «не имеет смысла». Когда ссылка хранится внутри структуры, она занимает столько же места, сколько и указатель. Кроме того, в следующем компилирует с лязгом:

struct MyStruct 
{ 
    //This will compile 
    union 
    { 
     struct { double& x; }; 
     double* x_ptr; 
    }; 
    //This won't compile; WHY? 
    /*union 
    { 
     double& x; 
     double* x_ptr; 
    };*/ 
    MyStruct(double& val) : x(val){} 
    void Repoint(double& new_value) 
    { 
     x_ptr = &new_value; 
    } 
}; 

Почему компилировать, когда ссылка завернутые в анонимной структуры, но не тогда, когда это только в союзе?

live example

ответ

8

В дополнение к @ Брайан: Вы можете сделать его компиляции, используя, например, std::reference_wrapper вместо простой ссылки:

#include <functional> 

struct MyStruct 
{ 
    //Stuff 
    union { std::reference_wrapper<double> x; double* x_ptr; }; 
    MyStruct(double& value) : x(value) {} 
    //More stuff 
}; 

int main() 
{ 
    double value = 123; 
    MyStruct myStruct(value); 
} 

live example

8

Это является незаконным объединением содержит опорный элемент. Это, по-видимому, потому, что ссылки не являются объектами, и неуказано, занимают они или нет, - поэтому нет смысла ссылаться на хранилище с другими переменными.

Объединение может иметь функции-члены (включая конструкторы и деструкторы), но не виртуальные (10.3) функции. Союз не должен иметь базовые классы. Объединение не должно использоваться в качестве базового класса. Если объединение содержит нестационарный элемент данных типа ссылочного типа, программа плохо сформирована.

([class.union]/2)

+0

Когда структура содержит ссылку, ссылка сохраняется как указатель. Нет никакой двусмысленности. –

+0

@JorgePerez Возможно. В некоторых случаях он также может быть оптимизирован. * Стандарт * не указан *. – Brian

Смежные вопросы