标记的联合C++

Cur*_*ous 2 c++ clang unions c++14

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

#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;
}
Run Code Online (Sandbox Code Playgroud)

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

g++ -std=c++14 some.cpp
Run Code Online (Sandbox Code Playgroud)

我收到很多编译错误

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.
Run Code Online (Sandbox Code Playgroud)

谢谢!

编辑:更新的代码仍然无法正常工作

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;
    }
};
Run Code Online (Sandbox Code Playgroud)

Sim*_*ple 9

std::string有一个不平凡的构造函数,所以你需要写的一个构造函数union执行一个放置news的位置.


这是一个代码的版本,它将构造函数添加到union.我不认为这是最好的解决方案,但它展示了您需要做的事情:

#include <iostream>
#include <new>
#include <string>
#include <utility>

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

struct TU {
    union my_union {
        struct i_type { int type; int i; } i;
        struct f_type { int type; float f; } f;
        struct s_type { int type; std::string s; } s;

        my_union(int i) : i{TU_INT, i} {}
        my_union(float f) : f{TU_FLOAT, f} {}
        my_union(std::string s) : s{TU_STRING, std::move(s)} {}
        my_union(my_union const& other) {
            // This is safe.
            switch (other.i.type) {
            case TU_INT:    ::new(&i) auto(other.i); break;
            case TU_FLOAT:  ::new(&f) auto(other.f); break;
            case TU_STRING: ::new(&s) auto(other.s); break;
            }
        }
        ~my_union() {
            // This is safe.
            if (TU_STRING == s.type) {
                s.~s_type();
            }
        }
    } u;

    TU(int i) : u(i) {}
    TU(float f) : u(f) {}
    TU(std::string s) : u(std::move(s)) {}
    TU(TU const&) = default;
    ~TU() = default;
};

int main() {
    TU tu("hello");
    std::cout << tu.u.s.s << '\n';
    return 0;
}
Run Code Online (Sandbox Code Playgroud)