Reputation: 7400
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
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.
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
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