c++ - 使用依赖于类型的模板名称的声明

标签 c++ templates grammar crtp

当在模板中使用 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 语法产生式没有包含 qualified-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

关于c++ - 使用依赖于类型的模板名称的声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15423283/

相关文章:

c++ - 异常未在辅助线程中捕获,从而导致段错误

c++ - 返回 shared_ptr 时的引用计数

c++ - 基于策略的设计中的模糊继承

C++ 函数透明地接受左值和右值参数

python - 如何使用 pybind11 包装模板类

rust - 在 Rust 中, "as"是运算符吗?

c++ - 如何使用 "Matlab Data/Engine API for c++"在 C++ 中加载 .mat

python - 在 python 中重命名 elif

c - 使用此语法在 flex/bison 中获取语法错误

c++ - 右值参数的模板类型推导