为什么C ++ 11没有模板typedef?

时间:2014-12-13 12:17:28

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

为什么C ++ 11没有“template typedefs”,比如

template<typename T> typedef std::vector<T, myalloc<T>> vec;

相反,他们只允许使用新语法:

template<typename T> using vec = std::vector<T, myalloc<T>>;

1 个答案:

答案 0 :(得分:8)

n1406是Herb Sutter关于“typedef templates”的提案,它模仿了你问题中的语法。提出“模板别名”的n1499取代它,它包含当前存在于C ++ 11中的using语法。

“typedef模板”的一个主要缺点在两篇论文中都有提到。从n1406开始:

  

在现有实践中,包括在标准库中,键入名称   嵌套在帮助器类模板中用于解决此问题   在许多情况下的问题。以下是这种惯例的一个例子   解决方法;主要缺点是在使用时需要编写:: Type   typedef'd name。

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模板”和   引入涉及“using”和“=”对的新语法来帮助   避免混淆:我们不是定义这里的任何类型,我们是   为 type-id 的抽象引入同义词(即别名)   (即类型表达式)涉及模板参数。如果模板   然后,在类型表达式的可推导上下文中使用参数   每当模板别名用于形成 template-id 时,   可以推导出相应模板参数的值 - 更多   接下来就是这样。无论如何,现在可以编写泛型   在可导出的背景下在Vec<T>上运行的函数,以及   语法也得到了改进。例如,我们可以将foo重写为:

template <typename T> void foo (Vec<T>&);
     

我们在此强调提出的主要原因之一   模板别名是为了使参数演绎和调用   foo(p)将成功。

因此,您可以看到n1499解决了n1406中的问题,并引入了更清晰,更易于阅读的语法。