【问题标题】:Type of non-type parameter in template template class is non deducible in C++14 but deducible in C++17模板模板类中非类型参数的类型在 C++14 中不可推导,但在 C++17 中可推导
【发布时间】:2019-03-06 23:11:06
【问题描述】:

标题有点混乱,但我的意思是这个具体案例:

template<class>
struct get_type_of_nontype;

template<class T, T Value, template<T> class Template>
struct get_type_of_nontype<Template<Value>> {
    using type = T;
};

所以我可以这样使用它:

#include <type_traits>

template<int I>
class int_non_type {};

static_assert(
    std::is_same<typename get_type_of_nontype<int_non_type<0>>::type, int>::value,
    "T is deduced to be `int` as `template<T> class Template` is `template<int> class int_non_type`"
);

这在 C++17 中运行良好。在 C++14 中出现以下错误:

gcc 8:

<source>:5:8: error: template parameters not deducible in partial specialization:
struct get_type_of_nontype<Template<Value>> {
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:5:8: note:         'T'

叮当声 7:

<source>:5:8: error: class template partial specialization contains a template parameter that cannot be deduced; this partial specialization will never be used [-Wunusable-partial-specialization]
struct get_type_of_nontype<Template<Value>> {
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:4:16: note: non-deducible template parameter 'T'
template<class T, T Value, template<T> class Template>
               ^

然后他们都抱怨struct get_type_of_nontype&lt;int_non_type&lt;0&gt;&gt; 不完整,所以typename get_type_of_non_type&lt;int_non_type&lt;0&gt;&gt;::type 无法编译。

为什么在 C++14 和 C++17 之间会有所不同?这只是一个编译器错误吗?如果没有,有没有办法在 C++14 中做到这一点?

【问题讨论】:

    标签: c++ templates c++14 c++17 template-templates


    【解决方案1】:

    [temp.deduct.type] 第 13 和 14 段中的标准措辞已更改。所以是的,您的示例在 C++14 中无效,但由于新的语言功能,在 C++17 中是允许的。

    C++14:

    模板类型参数不能从非类型模板参数的类型推导出来。

    [例子:

    template<class T, T i> void f(double a[10][i]);
    int v[10][20];
    f(v);           // error: argument for template-parameter T cannot be deduced
    

    -- 结束示例]

    C++17:

    当从表达式推导非类型模板形参P对应的实参值时,从表达式推导出P类型的模板形参的类型价值。 [例子:

    template<long n> struct A { };
    
    template<typename T> struct C;
    template<typename T, T n> struct C<A<n>> {
      using Q = T;
    };
    
    using R = long;
    using R = C<A<2>>::Q;    // OK; T was deduced to long from the
                             // template argument value in the type A<2>
    

    -- 结束例子] T[N]类型中N的类型是std::size_t。 [例子:

    template<typename T> struct S;
    template<typename T, T n> struct S<int[n]> {
      using Q = T;
    };
    
    using V = decltype(sizeof 0);
    using V = S<int[42]>::Q;  // OK; T was deduced to std::size_t from the type int[42]
    

    -- 结束示例]

    [例子:

    template<class T, T i> void f(int (&a)[i]);
    int v[10];
    void g() {
      f(v);         // OK: T is std::size_t
    }
    

    -- 结束示例]

    这似乎与另一个 C++17 模板更改有关:C++17 是第一个允许在非类型模板参数中使用占位符类型的版本,如 template &lt;auto Value&gt;template &lt;auto* Ptr&gt;。我希望编译器实现需要一些类似的逻辑来支持这两种语言特性。

    【讨论】:

    • 哦,所以 T 是从 T Value 而不是 template &lt;T&gt; class 推导出来的。这听起来像是在 C++14 中根本没有办法做到这一点。
    • 可能不会。除非您可能只需要支持有限的类型列表,例如算术类型,在这种情况下,您可以为每个类型编写一个特化。
    猜你喜欢
    • 1970-01-01
    • 2011-10-07
    • 1970-01-01
    • 2020-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多