在带有模板基的派生类中使用类型别名模板的声明

问题描述 投票:0回答:3

如果基类依赖于模板参数,则在非限定名称查找中不会检查其范围。我可以使用

using
声明来引入基类中的名称。假设现在我在基类中有一个类型别名模板。可以使用
using
声明将其引入到派生类中吗?

template<class T>
struct Base
{
    using Type1 = int;

    template<typename S>
    using Type2 = S;
};

template<class T>
struct Derived : Base<T>
{
    using typename Base<T>::Type1;           // Fine
    //using Type1 = typename Base<T>::Type1; // Also fine

    template<typename S>
    using Type2 = typename Base<T>::template Type2<S>;
};

Type2
的行可以替换为与
Type1
的(未注释的)行类似的内容吗?

c++ c++11 templates using
3个回答
0
投票
template<class T>
struct Derived : Base<T>
{
    using Base<T>::Type2;

    void foo() {
        // Using the Type2 alias template
        // inside our class to declare a local variable.
        typename Derived::template Type2<int> i;
    }
};

// Using the Type2 alias template
// outside the class to declare another type.
using X = Derived<int>::Type2<int>;

这是正确的语法,所有支持 C++11 的编译器都应该允许这样做。 请参阅此处的现场演示

我的意思是这样简单的东西:

using Base<T>::Type2;
,可能带有
typename
s 和
template
s。

我们在

using
声明中不需要这些消歧符,但是当我们想在
Type2
中使用
Derived
时,我们仍然需要:

  • template
    消歧器,因为
    Type2
    是一个模板,而
    Derived
    依赖于
    T
  • typename
    消歧符指定
    Type2<...>
    是一种类型

另请参阅:cpp 有关从属名称的参考文章


0
投票

这种语法解决的问题是,用作基本类型的潜在类型

Base<T>
可以在此定义之后但在
Derived
实例化之前进行专门化。

大多数时候,只要

Type2
是模板,这种语法就可以工作。这里可能的 XY 问题是您尝试获得更通用的语法。可悲的是,这是不可能的。解决方案只是将类型定义与
Derived
类分开。


0
投票

在C++中,我们可以使用

using typename Base<T>::Type1
从基类
Type1
引入类型名称
Base<T>
。使用
using typename Base<T>::template Type2
扩展此语法以引入模板名称
Type2
似乎很直观。但是,当前的 C++ 标准不支持此扩展。该提案可追溯到 1999 年,如 CWG109 中所述。

不合并此 using template 语法的一个原因是 C++11 中引入的 alias templates 的存在。正如您所提到的,别名模板提供了类似的功能,并且被认为是对使用模板的改进,尽管后者可能提供更简单的语法。引入使用模板的含义将能够创建模板模板

template<typename S>
using Type2 = typename Base<T>::template Type2;

我们如何实例化这个别名模板,它为每个未使用的类型参数

S
引入了一个模板?也许
Type2<int><int>
可以工作?然而,有人可能会反对这种用法。尽管我们可以通过措辞进行限制,但这种努力可能并不能证明结果的合理性。正如委员会的结论:

此时没有足够的动力进行改变。

那么,我们的选择是什么?考虑像下面这样的宏,它可能提供一种解决方法(demo):

#define USING_TEMPLATE(B, T)                                                   \
    template <class UTType> using T = typename B::template T<UTType>
// Example:
template <class T> struct B {
    template <class U> using Type = U;
};
template <class T> struct D : B<T> {
    USING_TEMPLATE(B<T>, Type);
    // The above macro expands to:
    // template <class UTType>
    // using Type = typename B<T>::template Type<UTType>;
    D() { (void)Type<int>(42); }
};
© www.soinside.com 2019 - 2024. All rights reserved.