如何实现std :: is_constructible <t,args =“”>?

时间:2016-07-04 09:34:49

标签: c++ c++11 typetraits c++-standard-library

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

1 个答案:

答案 0 :(得分:11)

来自cppreference

  

[我]变量定义T obj(std::declval<Args>()...);格式正确,value等于true,否则valuefalse

检查代码是否格式良好可以使用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...>;

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

Live on Coliru

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