是std::is_constructible<T, Arg1>
工作如果 Arg1
是一种可转换为 T
的有效单参数构造函数的类型?当类型具有非模板化转换运算符时,它似乎可以工作,但如果转换运算符是模板化的,则它不起作用(在某些编译器下)。
在下面的示例中,最终的 static_assert
在 GCC 7.2 和 clang 5.0 下失败,但在 MSVC 19 下通过。这里是否存在未定义的行为,或者编译器之一行为不当?
#include <type_traits>
struct foo
{
foo(int) {}
foo(int, int) {}
};
struct converts
{
template <class T>
operator T(){}
};
int main()
{
// These compile
foo f1(converts());
foo f2(converts(), converts());
static_assert(std::is_constructible<foo, converts, converts>::value, "foo(converts(), converts())");
// This line doesn't
static_assert(std::is_constructible<foo, converts>::value, "foo(converts())");
}
最佳答案
这只是一个最令人烦恼的解析问题。由于行 foo f1(converts())
可以被视为函数 f1
的声明,因此编译器必须 将其视为声明。如果将括号换成大括号,第一行将停止编译:
int main()
{
foo f1{converts()}; // Now broken
foo f2{converts(), converts()};
}
错误消息告诉我们编译器无法确定是否调用 foo(int)
、foo(const foo&)
或 foo (foo&&)
,因为 converts
也可以通过其模板化转换运算符转换为 foo
。
当您使用括号时,we can see通过使用 decltype
,编译器将 f1
视为 foo(converts(*)())
类型的函数声明 – 一个返回的函数foo
,它接受一个函数指针参数。
关于c++ - std::is_constructible 是否适用于可转换为参数的参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47564091/