在构造 std::variant 时禁用从指针类型到 bool 的隐式转换的最佳方法是什么? [英] What is the best way to disable implicit conversion from pointer types to bool when constructing an std::variant?

查看:19
本文介绍了在构造 std::variant 时禁用从指针类型到 bool 的隐式转换的最佳方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下事项:

struct foo {
};

struct bar {
};

int main()
{
    foo f;
    bar b;
    std::variant<foo*, bool> v;
    v = &b; // compiles in Visual Studio 19 v16.7.3
}

正如评论中所讨论的,我相信以上是合法的 C++17.有一个提议,P0608R3,这已被标准所接受,以解决这种令人惊讶的行为,但它在 2018 年(在圣地亚哥会议上)被接受,因此适用于 C++20 而不是 C++17.此外,P0608R3 目前未在 Visual Studio 中实现,即使编译到 C++20 预览版也是如此.

As discussed in comments, I believe the above is legal C++17. There is a proposal, P0608R3, that was accepted into the standard addressing this kind of surprising behavior, but it was accepted in 2018 (at the San Diego meeting) and thus applies to C++20 not C++17. Further P0608R3 is not currently implemented in Visual Studio, even when compiling to the C++20 preview.

从指向非 foo 的指针创建此变体的最佳/最不冗长的方法是编译时错误?我相信以下内容有效,但如果变体包含多个项目,则会有很多样板.

What is the best / least verbose way to make creation of this variant from a pointer that points to a non-foo a compile time error? I believe the following works but is a lot of boilerplate if the variant contains several items.

struct foo {
};

struct bar {
};

using variant_type = std::variant<foo*, bool>;
struct var_wrapper : public variant_type
{
    var_wrapper(foo* v = nullptr) : variant_type(v)
    {}

    var_wrapper(bool v) : variant_type(v)
    {}

    template<typename T>
    var_wrapper(T*) = delete;
};

int main()
{
    foo f;
    bar b;

    var_wrapper vw;
    vw = &f; // fine
    vw = true; // fine
    vw = &b; // compile time error
}

我错过了一些更简单的方法吗?

Am I missing some simpler way?

推荐答案

我认为处理隐式转换的最简洁方法是使用强变体"如果 std::variant 的行为有问题,请输入;即,实现一个变体类型,该类型仅使用完全变体中的类型来强制构造.

I think the cleanest way to handle implicit conversion doing surprising things with respect to variants is to use a "strong variant" type if the behavior of std::variant is a problem; i.e., implement a variant type that enforces construction only using types that are exactly the types in the variant.

在 C++17 中使用 std::disjunction 很容易测试一个类型是否是参数包的成员,导致如下实现:

It is easy to test if a type is a member of a parameter pack in C++17 using std::disjunction, leading to an implementation as below:

template<typename... Ts>
class strong_variant : public std::variant<Ts...> 
{
public:
    template <typename T, typename U = 
        typename std::enable_if<std::disjunction_v<std::is_same<T, Ts>...>>::type>
    strong_variant(T v) : std::variant<Ts...>(v)
    {}

    strong_variant() : std::variant<Ts...>()
    {}
};

struct foo {};
struct bar {};

int main()
{
    foo f;
    bar b;
    const foo c_f;

    strong_variant<foo*, std::string, bool> sv;

    sv = &f; // okay.
    sv = true; // okay.
    sv = "foo"s; // okay.

    sv = "foo"; //no, must a string.
    sv = &b;  // no, must be a foo.
    sv = &c_f; // no, must be non-const.
}

这篇关于在构造 std::variant 时禁用从指针类型到 bool 的隐式转换的最佳方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆