【发布时间】:2016-11-21 14:29:40
【问题描述】:
假设我有一个类 FunctionWrapper 定义如下:
struct FunctionWrapper
{
FunctionWrapper(std::function<void()> f);
// ... plus other members irrelevant to the question
};
我想防止从std::function<void()> 到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<>所需的隐式转换消耗了参数唯一允许的隐式转换。我假设您希望即使提供的参数已经是function<>? -
wrap(foo)已经是一个错误,并且永远是一个错误。wrap({foo})已经编译。我不明白你的问题。
标签: c++ implicit-conversion explicit uniform-initialization