n1406是 Herb Sutter 对“typedef 模板”的提议,它模仿了您问题中的语法。n1499它建议“模板别名”取代它,其中包含using
C++11 中当前存在的语法。
这两篇论文都解决了“typedef 模板”的主要缺点之一。从 n1406 开始:
在现有实践中,包括在标准库中,类型名称
嵌套在辅助类模板中用于解决此问题
很多情况下都会出现问题。以下是这种常见情况的一个示例
解决方法;主要缺点是使用时需要写::Type
typedef 的名称。
template< typename T >
struct SharedPtr
{
typedef Loki::SmartPtr
<
T, // note, T still varies
RefCounted, // but everything else is fixed
NoChecking,
false,
PointsToOneObject,
SingleThreaded,
SimplePointer<T> // note, T can be used as here
>
Type;
};
SharedPtr<int>::Type p; // sample usage, “::Type” is ugly
我们真正想要做的就是这样:
template< typename T >
typedef Loki::SmartPtr
<
T, // note, T still varies
RefCounted, // but everything else is fixed
NoChecking,
false,
PointsToOneObject,
SingleThreaded,
SimplePointer<T> // note, T can be used as here
>
SharedPtr;
SharedPtr<int> p; // sample usage, “::Type” is ugly
[...]
解决方法很难看,最好将其替换为
一流的语言支持,为用户提供自然的 C++ 模板
句法。
这种“一流的语言支持”以模板别名的形式出现。我们现在可以看看 n1499 所说的:
在本文中,我们将重点描述一种别名机制,该机制
允许 N1406 中提到的两种语义共存,而不是
被视为相互排斥。首先让我们考虑一个玩具示例:
template <typename T>
class MyAlloc {/*...*/};
template <typename T, class A>
class MyVector {/*...*/};
template <typename T>
struct Vec {
typedef MyVector<T, MyAlloc<T> > type;
};
Vec<int>::type p; // sample usage
这个习语的根本问题和主要动机
对于这个建议,习惯用法会导致模板参数
出现在不可演绎的上下文中。也就是说,将不可能
调用函数foo
下面没有明确指定模板
论据。
template <typename T> void foo (Vec<T>::type&);
另外,语法有点难看。我们宁愿避免嵌套
::键入呼叫。我们更喜欢像下面这样的东西:
template <typename T>
using Vec = MyVector<T, MyAlloc<T> >; //defined in section 2 below
Vec<int> p; // sample usage
请注意,我们特别避免使用术语“typedef template”并且
引入涉及“using”和“=”对的新语法来提供帮助
避免混淆:我们不是defining这里的任何类型,我们都是
为抽象引入同义词(即别名)type-id(即类型表达式)涉及模板参数。如果模板
参数在类型表达式的可推论上下文中使用,然后
每当模板别名用于形成模板 ID, 这
可以推导出相应模板参数的值 – 更多
接下来将对此进行介绍。无论如何,现在可以编写通用的
运行的函数Vec<T>
在可推论的背景下,并且
语法也得到了改进。例如我们可以重写foo
as:
template <typename T> void foo (Vec<T>&);
我们在此强调,提出这一建议的主要原因之一是
模板别名是为了参数推导和调用foo(p)
将会成功。
因此,您可以看到 n1499 解决了 n1406 中的问题,并引入了更清晰、更易于阅读的语法。