0

我想知道,是否可以在 C++0x 中创建一个静态类型的变体(其行为类似于自动):

variant<int, bool, std::string> v = 45;

当我们将 v 分配给 int 以外的值时,它不会编译:

v = true; //Compile error

到目前为止,我还没有找到任何优雅的解决方案。

4

3 回答 3

6

此代码在我的机器上使用 Boost.Variant 和 g++ 4.5 编译,适用于 C++98 和 C++0x。你想自己实现一个变体类型吗?然后你可能会研究 Boost 实现。

如果您想 /get/ 上述行为,您可以这样做:

auto v = 45;
static_assert(std::is_same<decltype(v), bool>
              || std::is_same<decltype(v), int>
              || std::is_same<decltype(v), std::string>,
              "v must be int, bool or string");

这应该和你描述的相当。

以下实施克林顿的建议:

template <typename T, typename... Args>
struct has_type;

template <typename T, typename Head, typename... Args>
struct has_type<T, Head, Args...>
{
    static const bool value = std::is_same<T, Head>::value
                              || has_type<T, Args...>::value;
};

template <typename T>
struct has_type<T> : std::false_type
{};

template <typename... Args, typename T>
T&& check_type (T&& t)
{
    static_assert(has_type<T, Args...>::value, "check_type");
    return std::move(t);
}

您只需要<memory>and<type_traits>为此并获得整数提升的完美转发和正确行为。

于 2011-03-22T08:21:36.367 回答
2

我认为,这是不可能的。

对象创建后,其静态类型不包含任何与对象初始化相关的信息。没关系,初始化用的是int或bool,变量的类型是一样的:

variant<int, bool, std::string>

赋值运算符只能在运行时分析内容,并在需要时抛出异常。

于 2011-03-22T08:35:14.987 回答
1

不,我认为你不能在编译时做到这一点。

您可以使用 enable_if 或类似方法启用或禁用一组赋值运算符,但将是每个类型,而不是每个实例。在一个编译单元中编译 v = true 时,我们如何知道您在另一个编译单元中使用了哪个构造函数?

于 2011-03-22T08:36:24.727 回答