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

How is std::is_constructible<T, Args> implemented?

本文关键字:何实现 实现 Args constructible is lt std gt      更新时间:2023-10-16

到目前为止我在网上找不到任何东西。对于一个学习项目,我想实现我自己的is_constructible。有人能解释一下它的工作原理吗?

From cppreference:

[I]如果变量定义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...>;

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,那么编译器本身必须提供一个内部函数来检索值。