【问题标题】:How do I pass a template super class type to a template base class?如何将模板超类类型传递给模板基类?
【发布时间】:2013-11-10 01:39:25
【问题描述】:

我正在尝试继承结构以添加 += 运算符。

这段代码看起来是对的,但编译失败,我从编译器得到的只是:

语法错误:在 ' 之前缺少 ',' 请参阅正在编译的类模板实例化“测试”的参考

struct plus_equals
{
    template<typename T, typename S>
    struct operator_type
    {
        S& operator+=(const T &other)
        {
            S* super = (S*)this;
            super->value += other;
            return *super;
        }
    };
};

template<typename T, typename OP>
struct Test : OP::operator_type<T, Test<T, OP>>   // error on this line
{
    T value;
    Test(T val) : value(val){}
};

int main(int argc, char *argv[])
{
    Test<int, plus_equals> test(123);
    test += 456;
    cout << test.value << endl;
    return 0;
}

我很困惑为什么下面的代码会编译,但上面的代码不会。

template<typename T>
struct Something
{
    T GetT() { return T(); }
};

class Test : public Something<Test>
{
    //...
};

【问题讨论】:

  • 我想你的意思可能是:template S& operator+=(const U &other),但这并不能解决问题。
  • 这在 llvm 中为我编译:struct Test : OP::template operator_type&lt;T, Test&lt;T, OP&gt; &gt; 你指出你得到了错误。
  • 哦..哇。我以前从未见过模板的用法,但它确实可以编译(vs2013)。如果你回答,我会接受。谢谢
  • 如果您知道如何将 Test 更改为可变参数模板并且仍然可以使用...那也太好了 =)

标签: c++ templates


【解决方案1】:

如果您使用template 关键字进行消歧,它将编译。

struct Test : OP::template operator_type<T, Test<T, OP> >

这里介绍了为什么这是必要的:Disambiguator template keyword for a template member of a template: when exactly?

【讨论】:

    【解决方案2】:

    您的代码的问题在于 operator_type 是一个模板,但编译器不知道将其视为一个模板,除非您将模板关键字放在它前面。

    #include <iostream>                                                                
    using namespace std;                                                               
    struct plus_equals                                                                 
    {                                                                                  
        template<typename T, typename S>                                               
        struct operator_type                                                           
        {                                                                              
            S& operator+=(const T &other)                                              
            {                                                                          
                S* super = (S*)this;                                                   
                super->value += other;                                                 
                return *super;                                                         
            }                                                                          
        };                                                                             
    };                                                                                 
    
    template<typename T, typename OP>                                                  
    struct Test : OP:: template operator_type<T, Test<T, OP>>   // error on this line
    {                                                                                  
        T value;                                                                       
        Test(T val) : value(val){}                                                     
    };                                                                                 
    
    int main(int argc, char *argv[])                                                   
    {                                                                                  
        Test<int, plus_equals> test(123);                                              
        test += 456;                                                                   
        cout << test.value << endl;                                                    
        return 0;                                                                      
    }   
    

    这个question 解释了如何完全解决依赖模板和类型名,以防问题再次出现。我还建议升级您的编译器,因为 clang 3.3 基本上会为您提供错误。这是我得到的不错的干净错误。

    这是一个非常更简单的问题解决方案

    #include <iostream>                                                                
    using namespace std;                                                               
    template<typename T, typename Orig>                                                
    struct operator_type                                                               
    {                                                                                  
        Orig & operator+=(const T &other)                                              
        {                                                                              
            static_cast<Orig*>(this)->value += other;                                   
            return *static_cast<Orig*>(this);                                           
        }                                                                              
    };                                                                                 
    
    template<typename T, template <class,class> class OP>                               
    struct Test : OP<T,Test<T,OP>>   // error on this line                             
    {                                                                                  
        T value;                                                                       
        Test(T val) : value(val){}                                                     
    };                                                                                 
    
    int main() {                                                                       
        Test<int,operator_type> t(10);                                                 
        t += 10;                                                                       
        cout << t.value << endl;                                                       
        return 0;                                                                      
    }
    

    【讨论】:

    • 我正在使用视觉工作室。还没有开始尝试clang..看起来是时候了=)
    • @bitwise MSVC 是出了名的糟糕,除非你真的知道你在做什么(并且需要它),否则我会远离 CRTP,更不用说你让这个案例比它更复杂了成为。
    • 如何让我的工作变得更简单?
    • @bitwise 我们不知道你用它做什么,但这显然是一种过于复杂的添加+= 运算符的方法,这对你有什么好处
    • @bitwise 也许只有我一个人,但我认为你的情况非常特殊
    猜你喜欢
    • 2017-12-25
    • 2020-07-12
    • 1970-01-01
    • 2011-04-04
    • 1970-01-01
    • 2018-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多