【问题标题】:How is std::is_constructible<T, Args> implemented? [duplicate]std::is_constructible<T, Args> 是如何实现的? [复制]
【发布时间】:2016-11-05 23:42:09
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

    来自cppreference

    [I]如果变量定义T obj(std::declval&lt;Args&gt;()...);是良构的,value等于true,否则value等于false

    可以使用 SFINAE 技术检查代码是否格式正确,例如 void_t&lt;&gt; 技巧(预计将成为 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&lt;&gt; 参数放在首位。它通常带有默认类型,但该位置由可变参数 Args 包持有。

    当为&lt;void, T, Args...&gt; 实例化is_constructible_ 时,编译器会首先尝试实例化特化。只有void_t&lt;...&gt; 的内容在语义上有效,即T(std::declval&lt;Args&gt;()...) 可以正确执行——如is_constructible 的要求中所指定,这才会成功。请注意,我使用的是临时变量而不是局部变量,但据我所知,两者之间的规则不会改变。特化继承自std::true_type,产生true value

    如果无法实例化特化(即T(std::declval&lt;Args&gt;()...) 无效),编译器将退回到总能实例化的通用模板。这个继承自std::false_type,产生falsevalue

    Live on Coliru

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

    【讨论】:

    • 这不完全等同于std::is_constructible,因为T(Arg) 等同于C 风格的演员——所以你的is_constructible&lt;intptr_t, int*&gt;true,而std 将返回假的。
    • 尝试template &lt;class T, class... Args&gt; struct is_constructible_&lt; void_t&lt;decltype(::new T(std::declval&lt;Args&gt;()...))&gt;, T, Args...&gt; : std::true_type {}; 获取专用模板。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-15
    • 2014-04-18
    • 2020-08-04
    • 1970-01-01
    • 1970-01-01
    • 2013-11-01
    • 2022-11-21
    相关资源
    最近更新 更多