【问题标题】:How can I use a nested type belonging to a templated class in another template function in C++?如何在 C++ 的另一个模板函数中使用属于模板类的嵌套类型?
【发布时间】:2019-08-26 00:28:05
【问题描述】:

我正在设置一个函数,该函数基于元组类型和函子结构 For 初始化元组,该函子结构具有 size_t 模板参数 INDEX 以保留编译时索引。这个函子也可能依赖于其他模板参数T...。因此,函子存在于保存这些模板参数的其他结构中(本例中为TClass)。

初始化函数(这里称为Bar)有一个template<std::size_t> class模板参数,以确保使用的类实际上可以存储索引。

虽然当我从非模板函数调用它时,我提出的设计工作正常,但如果函数的模板T2 确实确定了包装器TClass 的模板参数,则它不会编译。

这是包裹在TClass中的函子For的定义:

#include <cstdlib>

template <typename T> struct TClass {

    template<std::size_t INDEX> struct For {

        void operator()() {}
    };      
};

这是我想使用的函数调用:

template <template<std::size_t> class FOR> void bar() {
    //...
} 

template <typename T> void foo() {  
   bar<TClass<T>::For>(); //Does not compile
}

int main() {

    bar<TClass<int>::For>(); //Works
    foo<int>(); 

    return 0;
}

错误的foo-call 的编译器输出是:

error: dependent-name ‘TClass<T>::For’ is parsed as a non-type, but instantiation yields a type
    Bar<TClass<T>::For>(); //Does not compile

我知道依赖类型名称通常必须以typename 开头,但这对于第一个bar 调用也不是必需的。我认为这是因为模板参数只能解释为一种类型。所以我认为typename 可能会导致正确编译,但如果我将foo 更改为

template <typename T> void foo() {  
   bar<typename TClass<T>::For>(); //Does not compile
}

我明白了:

error: ‘typename TClass<int>::For’ names ‘template<long unsigned int INDEX> struct TClass<int>::For’, which is not a type
    Bar<typename TClass<T>::For>(); //Does not compile

我还提出了一个设计,其中TClass() 运算符依赖于模板INDEX,它也可以正常工作,因为不再需要使用嵌套类型。它看起来像这样:

#include <cstdlib>

template <typename T> struct TClass {

    template<std::size_t INDEX> void operator()() {}
};

template <typename FOR> void bar() {
    //...
} 

template <typename T> void foo() {  
   bar<TClass<T>>(); //Does compile
}

显然,在类型的模板由函数的模板参数确定的函数中,不可能使用依赖类型名称,但为什么呢?以及如何正确实施?为了使将来使用类型特征编写类型检查更容易,如果我可以使用仿函数,我会更喜欢它。

【问题讨论】:

    标签: c++ templates compiler-errors inner-classes


    【解决方案1】:

    编译器无法知道TClass&lt;T&gt;::For 在模板实例化的第一阶段引用了一个模板。它需要template 关键字的一些帮助。修复:

    template <typename T> void foo() {  
        bar<TClass<T>::template For>(); 
    }
    

    【讨论】:

    • 鉴于错误消息编译器清楚地确实知道,只是还不够快。即使这样也是可以解决的,但增加了足够的复杂性,使得该语言通过强制程序员显式来适应编译器编写者。
    • @KonradRudolph 为您添加了模板实例化的第一阶段
    • @MichaelVeksler 我能够重现原始错误并修复它。见ideone.com/8HuXan
    • @MaximEgorushkin 谢谢。我以某种方式假设我们只能将templatetypename 结合使用。所以 bar-call 在 main 中起作用,因为我们可以推断出 For 必须是模板类型,因为我们有关于所有模板的完整信息?
    • @StefanGroth 是的,在main 中已知TClass&lt;int&gt;::For 是一个模板。而在模板中,TClass&lt;T&gt;::For 可以在模板实例化的第一阶段引用任何内容,具体取决于 TTClass&lt;T&gt; 专业化。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    • 1970-01-01
    • 1970-01-01
    • 2011-05-04
    • 2022-07-19
    • 1970-01-01
    相关资源
    最近更新 更多