c++ - std::is_constructible 是否适用于可转换为参数的参数?

标签 c++ c++11 gcc visual-c++ clang

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())");
}

实例:https://godbolt.org/g/EcFqMP

最佳答案

这只是一个最令人烦恼的解析问题。由于行 foo f1(converts()) 可以被视为函数 f1 的声明,因此编译器必须 将其视为声明。如果将括号换成大括号,第一行将停止编译:

int main()
{
    foo f1{converts()}; // Now broken
    foo f2{converts(), converts()};
}

Live on godbolt

错误消息告诉我们编译器无法确定是否调用 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/

相关文章:

c++ - Thoughtworks游轮 : Unit Testing?

c++ - 在 C++ 中,派生类指针应该指向基类指针吗?

c++ - '-std=c++11' 对 C++/ObjC++ 有效,但对 C 无效

c++ - "undefined reference to"使用模板时链接器错误

c - 使用 scanf 处理多种数据类型

c++ - 为什么我不能在 mac 上使用 g++ 运行这个简单的 c++ 代码?

c++ - 二进制字符串转换为整数

c++ - Typedef是在C++编译时解析的吗?

c++ - lambda 主体内的重载静态成员函数调用无法编译

c++ - gcc : inline of virtual function and especially destructor in my case 中内联的行为