Reputation: 7809
I have a compile error in the following code. It seems that the compiler interprets class method set
as a template which - at first glance - is completely unrelated to my code.
#include <cassert>
#include <limits>
using namespace std;
template <class T>
class ReduceScalar{
public:
T get() { return *r; };
void set(T t) { *r = t; };
void set(T* t) { r = t; };
private:
T* r;
};
template <class T>
class ReduceSum : public ReduceScalar<T>
{
public:
ReduceSum(T* target) { set(target); set(0); } // COMPILE ERROR
};
Compiler gives the following error:
../test/../io/scalarreducers.h:34:26: error: use of class template 'set' requires template arguments
ReduceSum(T* target) { set(target); set(0); }
But I think it's because it thinks that set
is a template:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__tree:685:71: note: template is declared here
template <class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY set;
I do not understand why the compiler tries to instantiate that template for method set
and not just call method set
. How can I resolve this name confusion?
Upvotes: 1
Views: 89
Reputation: 33116
You will still have problems even if you get rid of that nasty using namespace std
. The problem is that member function set
may not exist in all instantiations. The code in the question uses set
as an unqualified, non-dependent name. This means two things:
set
at the point where the template is defined.ReduceScalar<T>
for member function set
. It can't because that member might not exist for all instantiations.End result: The code doesn't compile. The solution is to turn that non-dependent name into a dependent name. This defers resolution of dependent names until the template instantiation. One way to do this is to explicitly use this
(which is a dependent name).
template <class T>
class ReduceSum : public ReduceScalar<T>
{
public:
ReduceSum(T* target) { this->set(target); }
};
Alternatively, you can use the using declaration (very different from the using directive):
template <class T>
class ReduceSum : public ReduceScalar<T>
{
public:
using ReduceScalar<T>::set;
ReduceSum(T* target) { set(target); }
};
Upvotes: 6