如何实现std :: is_constructible <T,Args>?

Ale*_*lex 6 c++ type-traits c++-standard-library c++11

到目前为止我在网上找不到任何ELI5.对于学习项目,我想实现自己的is_constructible.有人可以解释它是如何工作的吗?

Que*_*tin 12

cppreference:

[I] f变量定义T obj(std::declval<Args>()...);是格式良好的,value等于true,否则value就是false.

检查代码是否格式正确可以使用SFINAE技术完成,例如void_t<>技巧(预计将成为C++ 1z标准库的一部分):

template <class...>
using void_t = void;

template <class, class T, class... Args>
struct is_constructible_ : std::false_type {};

template <class T, class... Args>
struct is_constructible_<
    void_t<decltype(T(std::declval<Args>()...))>,
T, Args...> : std::true_type {};

template <class T, class... Args>
using is_constructible = is_constructible_<void_t<>, T, Args...>;
Run Code Online (Sandbox Code Playgroud)

using箍跳跃在那里放置void_t<>第一个参数.它通常是最后一个默认类型,但该位置由可变参数Args包保存.

is_constructible_实例化时<void, T, Args...>,编译器首先尝试实例化特化.只有当内容void_t<...>在语义上有效时才能成功,也就是说,T(std::declval<Args>()...)可以正确执行 - 正如要求中所规定的那样is_constructible.请注意,我使用的是临时变量而不是局部变量,但据我所知,规则在两者之间不会发生变化.专业化继承自std::true_type,产生一个true value.

如果无法实例化特化(即,T(std::declval<Args>()...)无效),则编译器将回退到通用模板,该模板始终可以实例化.这个继承自std::false_type,产生了false value.

住在Coliru

更精确的特征,例如std::is_trivially_constructible,需要更高级的语言规则知识来制作表达,其有效性应该成为特征的价值.如果这证明在语言内部是不可行的,例如with std::is_standard_layout,那么编译器本身必须提供一个内部函数来检索值.

  • 这并不完全等同于 `std::is_constructible`,因为 `T(Arg)` 等同于 C 风格的转换 - 所以你的 `is_constructible&lt;intptr_t, int*&gt;` 是 `true`,而 `std ` 一个将返回false。 (2认同)