标记的联合C ++

时间:2016-02-26 09:51:18

标签: c++ clang c++14 unions

我正在尝试在c ++文件中编译以下标记的union,我遇到了问题。有人可以解释我缺少什么或我需要改变什么来让以下工作吗?我试过在网上看这个,不幸的是没有得到......

#include <string>
using std::string;
#include <iostream>
using std::cout;
using std::endl;
#include <new>

const int TU_STRING = 0;
const int TU_INT = 1;
const int TU_FLOAT = 2;

struct TU {
   int type;
   union {
     int i;
     float f;
     std::string s;
   } u;

   TU(const TU& tu) : type(tu.type) {
     switch (tu.type) {
       case TU_STRING: new(&u.s)(tu.u.s); break;
       case TU_INT:    u.i = tu.u.i;      break;
       case TU_FLOAT:  u.f = tu.u.f;      break;
     }
   }
   ~TU() {
     if (tu.type == TU_STRING)
       u.s.~string();
   }
};

int main() {
    TU tu;

    return 0;
}

我正在使用以下命令编译clang

g++ -std=c++14 some.cpp

我收到很多编译错误

some.cpp:18:4: error: call to implicitly-deleted default constructor of 'union (anonymous union at some.cpp:12:4)'
   TU(const TU& tu) : type(tu.type) {
   ^
some.cpp:15:18: note: default constructor of '' is implicitly deleted because variant field 's' has a non-trivial default constructor
     std::string s;
                 ^
some.cpp:18:4: error: attempt to use a deleted function
   TU(const TU& tu) : type(tu.type) {
   ^
some.cpp:15:18: note: destructor of '' is implicitly deleted because variant field 's' has a non-trivial destructor
     std::string s;
                 ^
some.cpp:20:13: error: use of undeclared identifier 'TU_STRING'
       case TU_STRING: new(&u.s)(tu.u.s); break;
            ^
some.cpp:20:34: error: unknown type name 'tu'
       case TU_STRING: new(&u.s)(tu.u.s); break;
                                 ^
some.cpp:20:36: error: expected ')'
       case TU_STRING: new(&u.s)(tu.u.s); break;
                                   ^
some.cpp:20:33: note: to match this '('
       case TU_STRING: new(&u.s)(tu.u.s); break;
                                ^
some.cpp:21:13: error: use of undeclared identifier 'TU_INT'
       case TU_INT:    u.i = tu.u.i;      break;
            ^
some.cpp:22:13: error: use of undeclared identifier 'TU_FLOAT'
       case TU_FLOAT:  u.f = tu.u.f;      break;
            ^
some.cpp:26:10: error: use of undeclared identifier 'tu'
     if (tu.type == TU_STRING)
         ^
some.cpp:26:21: error: use of undeclared identifier 'TU_STRING'
     if (tu.type == TU_STRING)
                    ^
some.cpp:25:4: error: attempt to use a deleted function
   ~TU() {
   ^
some.cpp:15:18: note: destructor of '' is implicitly deleted because variant field 's' has a non-trivial destructor
     std::string s;
                 ^
some.cpp:32:8: error: no matching constructor for initialization of 'TU'
    TU tu;
       ^
some.cpp:18:4: note: candidate constructor not viable: requires single argument 'tu', but no arguments were provided
   TU(const TU& tu) : type(tu.type) {
   ^
11 errors generated.

谢谢!

编辑:更新的代码仍无效

struct VariantType {

    enum class Tag {INTEGER, STRING};
    Tag tag;
    union TypeUnion {
        string inner_string;
        int inner_int;

        TypeUnion(const std::string& str) {
            new(&inner_string) string(str);
        }
        TypeUnion(int inner_int_in) {
            inner_int = inner_int_in;
        }
        TypeUnion(std::string other) : inner_string{std::move(other)} {}
    } type_union;

    VariantType(const std::string& str) : tag{Tag::STRING} {
        new(&this->type_union.inner_string) string(str);
    }
    VariantType(int inner_int_in) : tag{Tag::INTEGER} {
        this->type_union.inner_int = inner_int_in;
    }
};

1 个答案:

答案 0 :(得分:8)

std::string有一个非平凡的构造函数,因此您需要为在union位置执行展示位置new的{​​{1}}编写构造函数

以下是代码的一个版本,它将构造函数添加到s。我不认为这是最好的解决方案,但它证明了你需要做的事情:

union