CuriousGeorge
CuriousGeorge

Reputation: 7400

How do I pass a template super class type to a template base class?

I am trying to inherit a struct in order to add a += operator.

This code seems right, but it fails to compile, and all I get from the compiler is this:

syntax error : missing ',' before '<'
see reference to class template instantiation 'Test' being compiled

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;
}

I'm confused why the code below will compile, but the above will not.

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

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

Upvotes: 1

Views: 341

Answers (2)

aaronman
aaronman

Reputation: 18750

The problem with your code is that operator_type is a template but the compiler doesn't know to treat it as one unless you put the template keyword in front of it.

#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;                                                                      
}   

This question explains how to resolve dependent templates and typenames fully incase the problem comes up again. I would also suggest upgrading your compiler as clang 3.3 basically spoon-feeds you the error. Here is the nice clean error I get. enter image description here

Here is a much simpler solution to the problem

#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;                                                                      
}

Upvotes: 1

Phillip Kinkade
Phillip Kinkade

Reputation: 1432

If you use the template keyword for disambiguation, it will compile.

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

Why this is necessary is covered here: Disambiguator template keyword for a template member of a template: when exactly?

Upvotes: 1

Related Questions