“template<typename T, T t>”习惯用法是什么?

23
我正在阅读这篇文章,并试图理解什么是N3601。它说在网络搜索中经常出现这个习语,但我找不到任何信息。这是什么?
template<typename T, T t>

成语是什么,它解决了什么问题,如何使用它,隐式模板参数是什么,提案的目的是什么?


2
从一个模板开始 template <typename T> void foo(T t);。将该参数变为编译时值:template <typename T, T t> void bar();(我认为您是指这个而不是 class)。现在考虑如何调用 foo(5); 使 T 成为 int,但要使用 bar,您需要 bar<int, 5>();。这样做是否朝着正确的方向发展? - chris
我是指 T t,而不是类 T。已修复。 - Jorge Ortega
@chris 我现在明白你的意思了。bar需要对我们给定的任何类型都是通用的,但也将该类型的值作为另一个模板参数。我们需要同时指定类型和值,以便推断出5是int类型。这个提案展示了在反射库中使用它的用法,但我今天之前从未见过它。还有其他什么用途吗? - Jorge Ortega
+1. 啊!我喜欢这个提议。我认为它可能会帮助我解决这个问题,而这个问题无法用C++11解决。 - Nawaz
1
@Nawaz,说得好。我实际上还没有考虑过它在这方面能够比C++11做些什么。 - chris
太酷了,这么多人对新的C++感兴趣。 - innochenti
2个回答

15
被解决的问题是从模板非类型参数中推断类型。 给定:
template<typename T> void foo(T);
template<typename T, T> void bar();

foo中,可以推断出T(例如,foo(10)的结果将导致T被推断为int),但是在bar中无法推断出Tbar<10>()将无法编译,您必须将其编写为bar<int,10>())。

N3601提议通过引入以下语法来修复此问题:

template<using typename T, T> void bar();

这将允许bar<10>()编译,并导致类型T被推断出来。


5
这篇文章的介绍有误导性:实际上该习语是
 template <typename T, T t>

这是一个基于类型 T 和该类型的值 t 的模板。尽管在大多数情况下类型可以从值中推断出来,但表示方法有点繁琐。

例如:

// the current definition notation
template <typename T, T t> void f() { t.f(); };

//// the proposed definition notation
//// the parameter t depends on an implicit typename parameter T
// template <using typename T, T t> void f() { t.f(); };

struct foo {
    void f(){ 
        // some computation
    }
};

foo bar;

int main(){
    // the current instantiation notation
    f<foo,bar>(); 
    //// the proposed instantiation notation 
    //// we know that bar is of type foo, so we don't need to specify it
    // f<bar>();
}

该提案旨在引入一些“语法糖”,以使符号更易于书写。
此外,上面给出的示例在其描述中是微不足道的(并且可能是错误的,因为模板参数需要是constexpr),但该论文描述了几种情况,当前符号表示法可能变得非常复杂,降低可读性和整体编程便利性。

该类型的值t必须是整数常量或指针,因为模板参数中不允许出现其他内容。 - v.oddou

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接