【问题标题】:Prevent implicit conversion but allow list initialisation?防止隐式转换但允许列表初始化?
【发布时间】:2016-11-21 14:29:40
【问题描述】:

假设我有一个类 FunctionWrapper 定义如下:

struct FunctionWrapper
{
  FunctionWrapper(std::function<void()> f);

  // ... plus other members irrelevant to the question
};

我想防止从std::function&lt;void()&gt;FunctionWrapper 的隐式转换,但允许使用大括号初始化语法(即使用带有单个参数的列表初始化)构造FunctionWrapper。换句话说,我想要这样:

void foo();
void wrap(FunctionWrapper);

wrap(foo); // (1) error
wrap({foo}); // (2) OK
wrap(FunctionWrapper{foo}); // (3) OK

有没有办法做到这一点?我在上面定义类的方式不是这样:这允许隐式转换,所以 (1) 编译。

如果我在构造函数中添加explicit

struct FunctionWrapper
{
  explicit FunctionWrapper(std::function<void()> f);

  // ... plus other members irrelevant to the question
};

它也无济于事,因为这“太过分”并且不允许(2)和(1)。

有没有办法实现“中间立场”并让 (2) 编译而 (1) 产生错误?

【问题讨论】:

  • 添加一个带有std::initializer_list参数的显式构造函数。
  • 你可以使用 initializer_list 但是你只能在运行时检查参数的数量......也许模板接受 const 数组和模板大小上的 static_assert ......但这很难看
  • @Hcorg 不会 this 需要双括号初始化吗?
  • 在您的第一个示例中,only the first won't fail to compile already, 因为从函数指针到function&lt;&gt; 所需的隐式转换消耗了参数唯一允许的隐式转换。我假设您希望即使提供的参数已经是 function&lt;&gt;?
  • wrap(foo) 已经是一个错误,并且永远是一个错误。 wrap({foo}) 已经编译。我不明白你的问题。

标签: c++ implicit-conversion explicit uniform-initialization


【解决方案1】:

有没有办法做到这一点?

是的。你已经有了。

wrap(foo);

为此,需要进行两次用户定义的转换:void(*)() --&gt; std::function&lt;void()&gt; --&gt; FunctionWrapper,但我们最多只能进行一次用户定义的转换。所以这是一个错误,除非你向FunctionWrapper 添加一个单独的构造函数来允许它。

wrap({foo}); 

这已经很好了,我们正在复制列表初始化FunctionWrapper,因此上述限制不适用。

wrap(FunctionWrapper{foo});

这显然很好。


请注意,这也为您的第一个示例实际有效的情况提供了一条前进的道路。假设你有:

struct Wrapper {
    Wrapper(int ) { }
};

foo(0);           // want this to fail
foo({0});         // want this to be OK
foo(Wrapper{0});  // ... and this

您不能创建构造函数explicit,因为这也会导致foo({0}) 失败。但是您可以简单地使用另一个包装器添加另一个间接层:

struct AnotherWrapper {
    AnotherWrapper(int i): i{i} { }
    int i;
};

struct Wrapper {
    Wrapper(AnotherWrapper ) { }
};

这里,wrap(0) 失败,但 wrap({0})wrap(Wrapper{0}) 都可以。

【讨论】:

    猜你喜欢
    • 2016-04-27
    • 2015-01-12
    • 1970-01-01
    • 2015-07-13
    • 1970-01-01
    • 2020-04-14
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多