将模板类型参数作为模板非类型参数传递

时间:2018-11-22 09:12:03

标签: c++ c++11 templates language-lawyer c++17

很好奇:在C ++ 17和更高版本中,我们可以为非类型模板参数使用auto占位符:

template<typename A, auto B>
class C {
public:
    A foo() { return B; }
};

但是我们可以代替模板类型参数auto来代替A吗?

example.cpp

template<typename A, A B>
class C {
public:
    A foo() { return B; }
};

int main()
{
    C<int, 5> c;
    std::cout << c.foo() << std::endl;

    return 0;
}

实际上,我们可以做到这一点,并且-std = c ++ 11的clang允许这样做。

$ g++ -std=c++11 example.cpp
$ ./a.out
5

那么标准呢?我没有为此找到任何明确的规则。 谢谢!

2 个答案:

答案 0 :(得分:1)

模板参数可以分为:

1. Type parameters
2. Non type parameters
3. Template template parameters

在您的情况下,语句A B是非类型模板参数,其类型是模板类型参数A

请记住,在您的示例中,您这样做:

return B;

上面的语句将在非A的类型copy constructible上失败(这很容易用一个概念表示)。

请牢记(如注释中所指出),C ++ 17强制执行复制省略。

答案 1 :(得分:1)

  

但是我们可以传递而不是定义在左侧的“自动”模板类型参数吗?

好的。这是旧方法。

但是auto方式可以避免传递类型A

在C ++ 17中,您可以编写

template <auto B>
class C {
public:
    auto foo() { return B; }
};

因此无需传递类型A

我不知道在C ++ 11 / C ++ 14中也可以做到这一点。

我的意思是:如果需要,在C ++ 11 / C ++ 14中将值传递给模板...如果类型是固定的,就没有问题

template <int I>

但是类型本身可以不同,在C ++ 11 / C ++ 14中,您必须先传递类型,然后再传递值,如您的example.cpp

template <typename T, T A>

旧的问题是,如果您要调用这种类型的模板,则必须多余,并写为

C<decltype(x), x>  some_C_variable;

而我所知避免这种冗余的唯一方法是通过make函数(例如make_tuple())或C风格的宏。

在C ++ 17中,您可以简单地编写

C<x>   some_C_variable

,并且在C模板类/结构内部,可以从x获得decltype(B)的类型。

对于C ++ 17标准参考...

首先,将auto定义为“占位符”

从10.1.7.4(auto说明符)开始,指向第1点

  

autodecltype(auto) type-specifier 用于指定占位符类型,该占位符类型稍后将通过初始化程序的推导来替换。

在C ++ 11 / C ++ 14中也是如此

但是C ++ 17标准在第4点枚举中为“模板参数”(17.1)添加了新点4.6

  
      
  1. 非类型 template-parameter 必须具有以下(可选的cv限定)类型之一:
  2.   
     

[...]

     

(4.6)包含占位符类型(10.1.7.4)的类型