使C++初始值设定项自动检测工会成员

Make a C++ initializer automatically detect union member?

本文关键字:自动检测 成员 C++      更新时间:2023-10-16

好的,标准仍然说大括号初始化联合只初始化第一个成员。 我想这把这个问题更多地放在"如果......不是很好吗?"类别中。

一定要这样吗?毕竟,我们现在有其他类型的自动类型检测。

auto x = 3; // int
auto s = "foo"; // char *
auto w = L"Foo"; // wchar_t *

那么为什么不成立工会呢?鉴于:

struct init 
{
 int t;
 union {
   long long x;
   char *s;
   wchar_t *w;
 };
};

目前您只能用大括号初始化init::x(带有int),而不能sw

可以扩展自动类型检测,以便根据初始值设定项的类型选择已初始化的联合成员:

auto init initial_data [] = {
 { 0, 3 },      // initializes x, brace elision
 { 1, "foo" },  // initializes s 
 { 2, L"Foo" }  // initializes w
};

(当然,这不应该在当前标准中编译。

这样就可以将所有initial_data放在单个初始值设定项列表中。(我怀疑 auto 关键字必须去其他地方)。

是否有什么东西使这是一个坏主意(除了"还没有人想到它"或"它太难实现")? 目前,您必须做一些可怕的事情,例如:

#define RI(X) reinterpret_cast<long long>(X)
const init initial_data[] = {
{ 0, 3 },      // initializes x, brace elision
{ 1, RI("foo") },  // initializes s 
{ 2, RI(L"Foo") }  // initializes w
};

我不想经历这些扭曲,除了必须用std::string初始化std::exception(即基于 char),所以我不能只有一个包含所有wchar_t*的初始值设定项列表。 我真的很想把所有这些初始值设定项都放在同一个地方。

更新

在我的介绍中,我提到:

尽管联合可以具有成员函数(包括构造函数和析构函数)

我刚刚意识到这使您能够自己编写所需的构造函数!

struct init {
    init(long    long   v) : t(type::longlong), x(v) {}
    init(char    const* v) : t(type::pcsz),     s(v) {}
    init(wchar_t const* v) : t(type::pwcsz),    w(v) {}
    enum class type { longlong, pcsz, pwcsz } t;
    union { long long x; char const* s; wchar_t const* w; };
};

现在编译:

init initial_data [] = {
    3 ,      // initializes x, brace elision
    "foo" ,  // initializes s 
    L"Foo"   // initializes w
};

科里鲁现场观看


问。是否有什么东西使这是一个坏主意(除了"还没有人想到它"或"它太难实现")

一般来说,union通常是一个坏主意。很难安全地使用它们。在这方面,他们在C++有点"二等"公民(尽管现在联盟可以有成员函数(包括构造函数和析构函数),但不能有虚函数)。

让编译器选择"the"槽来接收初始值设定项可能很快就会遇到歧义。

通过大括号初始化,他们可以添加一些限制(没有缩小/扩大转换),就像 C++11 中的初始值设定项列表一样。

但这都是幻想。简而言之:这不是语言功能


boost::variant有这种行为。

笔记

  • which()成员基本上是你的类型鉴别器(t
  • 您可以针对大小进行优化: BOOST_VARIANT_MINIMIZE_SIZE
  • 如果要
  • 从文字分配,则应const*字符/wchar_t指针!

住在科里鲁

#define BOOST_VARIANT_MINIMIZE_SIZE
#include <boost/variant.hpp>
using init = boost::variant<long long, char const*, wchar_t const*>;
#include <iostream>
int main() {
    init initial_data [] = {
        3 ,      // initializes x, brace elision
        "foo" ,  // initializes s 
        L"Foo"   // initializes w
    };
    for(auto& v : initial_data)
        std::cout << v.which() << "t" << v << "n";
}

输出:

0   3
1   foo
2   0x401f14