C++大括号初始值设定项作为参数调用不同的构造函数,然后预期
C++ brace initializer as an argument calls different constructor then expected
最小的例子是这样的类:
class Chain {
public:
Chain(std::string name, std::vector<int> args)
{
assert(true);
}
Chain(std::string name, bool flag)
{
assert(false);
}
};
用法如下
int main() {
auto ch = Chain("name", {});
return 1;
}
Chain
的第二个构造函数以前没有bool flag
,我必须添加它,现在代码Chain("name", {})
调用第二个构造函数(在它调用第一个构造函数之前(。
我想我会改变第二个构造函数的参数顺序
Chain(bool flag, std::string name)
{
assert(false);
}
但即便如此,它也会将const char *
强制转换为bool
,{}
强制转换为std::string
然后调用第一个构造函数。
有没有办法禁止它/强制使用调用第一个 ctor?
使用显式类型。
auto ch1 = Chain("name", std::vector<int>{});
auto ch2 = Chain("name", true);
重载解析规则很复杂:
以下任何重载都是可行的:
Chain(std::string name, std::vector<int> args); #1
Chain(std::string name, bool flag); #2a
Chain(bool flag, std::string name); #2b
为
Chain("name", {});
但#2a
和#2b
都是比#1
最好的候选人,特别是因为:
1( 标准转换序列总是优于用户定义的转换序列或省略号转换序列。
所以{} -> bool
比{} -> std::vector<int>
好,const char* -> bool
比const char* -> std::string
好({} -> std::vector<int>
相当于{} -> std::string
(。
我建议在bool
周围添加一个包装类,如下所示:
struct bool_wrapper
{
// bool_wrapper() : b(false) {} // would make your call ambiguous.
bool_wrapper(bool b) : b(b) {}
operator bool() const {return b;}
bool b = false;
};
然后
Chain(std::string name, bool_wrapper flag); // To fix overload resolution
演示
演示与模棱两可的调用
如果您不能像Chain("name", std::vector<int>{});
那样修改对第一个构造函数的调用,我可以建议两种方法。
如果对第一个构造函数的调用始终使用字符串文本(如"name"(不是 std::string(执行,则可以修改这两个构造函数:
class Chain {
public:
Chain(const char* name, std::vector<int> args)
{
assert(true);
}
Chain(bool flag, const std::string& name)
{
assert(false);
}
};
如果上述假设为 false,则可以将虚拟参数添加到第二个构造函数中:
class Chain {
public:
Chain(std::string name, std::vector<int> args)
{
assert(true);
}
Chain(std::string name, bool flag, bool dummy)
{
assert(false);
}
};
以及不需要修改构造函数的奖励解决方案:
class Chain {
public:
Chain(const std::string& name, std::vector<int> args)
{
assert(true);
}
template<typename T>
Chain(const std::string& name, T flag);
};
template<>
Chain::Chain(const std::string& name, bool flag)
{
assert(false);
}
相关文章:
- 为什么即使我调用参数化构造函数也会调用默认构造函数?
- 什么是仅调用一次并调用参数的控制台应用
- 调用参数排列不变函数 f(i++, i++)
- 调用参数不是原子参数的函数是此代码引发异常的原因吗?
- 如何使可调用参数的签名在C++模板中可见?
- x64 函数调用参数推送/移动顺序 (MSVC)
- 如何调用参数由另一个函数生成的函数?
- 从从可调用参数创建的线程对象参数移动构造 C++11 线程
- 正确调用参数化 std::函数
- 是否允许在调用参数中使用类型名 T
- 我不知道如何调用参数为节点类型的函数
- 函数调用参数列表 (C++) 中的空格
- Valgrind 错误:系统调用参数 epoll_pwait(sigmask) 指向不可寻址的字节
- 这C++代码如何让我调用参数数量错误的函数
- 在计算后,在基类之后调用参数化构造函数
- NPAPI调用参数包装
- 在类组合中调用参数化构造函数
- 为什么在创建类对象数组时不能调用参数化构造函数?
- 如何在 for 循环中调用参数化构造函数
- 如何在PIMPL设计模式中调用参数化构造函数