std::is_constructible<T, Args>是如何实现的?
How is std::is_constructible<T, Args> implemented?
到目前为止,我在网上找不到任何 ELI5。对于一个学习项目,我想实现我自己的 is_constructible。有人可以解释一下它是如何工作的吗?
来自 cppreference:
[I]f the variable definition T obj(std::declval<Args>()...);
is well-formed, value
is equal to true
, else value
is 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
.
更精确的特征,例如 std::is_trivially_constructible
,需要更高级的语言规则知识来制作其有效性应成为特征值的表达式。如果从语言内部证明这是不可行的,例如 std::is_standard_layout
,那么编译器本身必须提供一个内部函数来检索值。
到目前为止,我在网上找不到任何 ELI5。对于一个学习项目,我想实现我自己的 is_constructible。有人可以解释一下它是如何工作的吗?
来自 cppreference:
[I]f the variable definition
T obj(std::declval<Args>()...);
is well-formed,value
is equal totrue
, elsevalue
isfalse
.
可以使用 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
.
更精确的特征,例如 std::is_trivially_constructible
,需要更高级的语言规则知识来制作其有效性应成为特征值的表达式。如果从语言内部证明这是不可行的,例如 std::is_standard_layout
,那么编译器本身必须提供一个内部函数来检索值。