使用类型依赖模板名的声明

Using declaration for type-dependent template name

本文关键字:声明 类型 依赖      更新时间:2023-10-16

当CRTP在模板内部使用时,(或者通常当模板形参作为基类模板实参传递时),是否不可能在using声明中命名基类的成员模板?

template< typename d >
struct base {
    template< typename >
    struct ct {};
    template< typename >
    void ft() {}
};
template< typename x >
struct derived : base< derived< x > > {
     using derived::base::template ct; // doesn't work
     using derived::base::ft; // works but can't be used in a template-id
};

在我看来,这是语言中的一个漏洞,仅仅是因为using-declaration语法产物没有包含限定id

using-declaration:
    using typename(opt) nested-name-specifier unqualified-id ; // have this
    using :: unqualified-id ;
unqualified-id:
    identifier
    operator-function-id
    conversion-function-id
    literal-operator-id
    ~ class-name
    ~ decltype-specifier
    template-id
qualified-id:
    nested-name-specifier template(opt) unqualified-id // want this
    :: identifier
    :: operator-function-id
    :: literal-operator-id
    :: template-id

如果唯一的规则是using-declaration: using typename(opt) qualified-id,那么唯一的结果将是

  • 排除了没有语义意义的:: conversion-function-id:: ~ class-name:: ~ decltype-specifier template-id
  • 允许7.3.3/5明确禁止的:: template-id,以及
  • 允许template关键字已经有足够的规格来修补漏洞。

这个分析正确吗?

如果允许新的语法,也许带typename的声明应该导入一个类模板或别名模板,而不带typename的声明应该导入一个函数或变量模板到当前作用域。

     using typename derived::base::template ct;
     using derived::base::ft;

这可能需要一些额外的规范。此外,目前的现状似乎是,依赖的模板名总是有模棱两可的类型(不是模板id),所以不清楚typename属于ct

下面的代码可以在c++ 11中正常运行:

#include <iostream>
template< typename d >
struct base {
    template< typename >
    struct ct {};
    template< typename >
    void ft() {std::cerr << "cheesecake" << std::endl;}
};
template< typename x >
struct derived : base< derived< x > > {
  template<typename X>
    using ct = typename derived::base::template ct<X>; // new in C++11
  using derived::base::ft;
};
int main()
{
  derived<int>::ct<float> c;
  derived<int> a;
  a.ft<int>();
}

如果这不是你想要的,你能举例说明你想如何使用ctft吗?