如何消除此模板的歧义
How to disambiguate this template?
我有一个类,它将大小作为模板参数(实时演示):
template <std::size_t SIZE> class A
{
char b[SIZE];
}
它有多个用于不同目的的构造函数:
using const_buffer_t = const char (&)[SIZE];
using my_type = A<SIZE>;
A() : b{} {} // (1) no params
A(const_buffer_t) : b{} {} // (2) copy contents of given buffer
A(const char * const) : b{} {} // (3) copy as many items as they fit into the size
explicit A(const my_type &) : b{} {} // (4) copy constructor
// (5) copy as many items as they fit into the size
template <std::size_t OTHER_SIZE>
A(const char (&)[OTHER_SIZE]) : b{} {}
// (6) copy constructor from another sized A
// copy as many items as they fit into the size
template <std::size_t OTHER_SIZE>
explicit A(const A<OTHER_SIZE> &) : b{} {}
有了这组构造函数,以下指令没有问题:
// CASE 1
// Calls constructor 3: A<5>(const char * const)
// Expecting constructor 5: A<5>(const char (&)[11])
A<5> a("0123456789");
// CASE 2
// As expected, calls constructor 1: A<5>()
A<5> b();
// CASE 3
// As expected, calls constructor 4: A<5>(const A<5> &)
A<5> c(b);
// CASE 4
// As expected, calls constructor 6: A<5>(const A<9> &)
A<9> c(b);
但是当调用A<5>("five")
时,构造函数2、3、4和5之间有一个不明确的调用。
所以我的问题是:
- 为什么在CCD_ 2中构造函数3优先于构造函数5
- 当用与模板参数大小相同的静态数组构造对象
A<SIZE>
时,是否有方法消除构造函数2、3、4、5的歧义
感谢您的关注。
在过载解析期间对转换序列进行排序时,数组到指针的转换被认为是完全匹配的(C++11 13.3.3.1.1/1表12)。与你的直觉相反,这意味着(3)和(5)对于A<5> a("0123456789");
是同样好的匹配。正如Xeo在评论中所说,平局被打破了,取而代之的是非模板(3)。你可能会想把(3)也变成一个模板来欺骗编译器:
template <typename=void>
A(const char * const) : b{} {}
但这样做只会导致结构的模糊性。确实没有简单的方法来消除const char (&)[]
和const char*
过载的歧义:最好的解决方案可能是更改(3)以接受指针和长度:
A(const char * const, std::size_t) : b{} {
std::cout << "size: " << SIZE << " ctor 3n";
}
顺便说一句,我将注意到,向const char* const
构造函数添加size_t
参数也可以消除A("five")
情况的歧义。
编辑:然而,有一种合理的方法可以消除char*
构造函数与数组构造函数的歧义,通过引用接受指针参数:
template <typename T,
typename=typename std::enable_if<
std::is_same<typename std::remove_cv<T>::type, char>{}
>::type>
A(T* const&) : b{} { std::cout << "size: " << SIZE << " ctor 3n"; }
[这个特殊的把戏要归功于dyp,可能还有Johannes Schaub、Yakk或我(我很确定不是我)。]
在数组到指针的转换发生之前,该模板通过引用有效地锁定到实际类型上,然后将引用约束为非指针类型。
-
为什么在CASE 1中,构造函数3比构造函数5更受欢迎?
答案:由于过载解决方案。非模板化类函数是第一类公民,因此具有比模板化函数更高的重载解析级别。因此,与模板构造函数5相比,构造函数3是优选的。
相关文章:
- 构造对象的歧义
- 函数何时会在c++中包含stack_Unwind_Resume调用
- Python中的for循环与C++有何不同
- 如何在GTK程序运行时禁用屏幕保护程序/电源管理/屏幕消隐
- 我知道函数调用中存在歧义.有没有办法调用foo()函数
- 在C++中释放内存期间,迭代器与指针有何不同
- 数组初始值设定项的构造函数歧义
- 消除好友和成员二进制运算符的歧义
- 用' . '代替' :: '会在C++中造成歧义吗?
- 为什么下面带有非常量转换函数的代码没有歧义?
- 标准对此指向成员函数类型模板参数有何说明?是我的代码有误,还是 MSVS 16.6 有问题?
- std::bind 是否实现了 std::ref 和 std::cref 来消除函数调用的歧义?
- 类中的 C++ int 被设置为值,似乎不知从何而来
- 使用 bool 和 const char 重载的 C++ 函数会在没有警告的情况下产生歧义 (MSVC2012)
- -fvisibility-inline-hidden 与 gcc 中的 -fvisibility=hidden 有何不同
- C++SFINAE enable_if_t成员函数,如何消除歧义?
- 多重继承相同的方法名,没有歧义
- 如何在模板化转换运算符中消除此构造的歧义?
- 当存在覆盖歧义函数时,代码如何运行?
- Visual Studio 2017中的哪些扩展在传入lambda时消除了"bool"与"std::function"的歧义?