apalomer
apalomer

Reputation: 1935

Not being able to instantiate templated class with templated method without arguments

I am trying to develop a class that has to be templated and needs to have some templated methods. I have been looking and, most likely because I do not know how to explain my problem, I have not been able to find the solution. Here is my exmaple:

template<typename T>
class TestClass{
public:
    template<typename M>
    TestClass(M val): val_(T(val)){}

    template<typename N>
    N func() {
        return N(val_);
    }

    T get() {
        return val_;
    }

    template<typename N>
    N add(N val) {
       return N(val_) + val;
   }

private:
    T val_;
};

This class will be called in templated functions such as this one:

template<typename T>
std::string str(TestClass<T> f)
{
    std::ostringstream out;
    out << f.func<T>();
    out << "\n";
    out << "get: ";
    out << f.get();
    out << "\n";
    out << f.add<T>(0.0);
   return out.str();
}

An here is an example of usage:

int main(int argc, char** argv){

   TestClass<double> t('a');
    std::cout<<"Manual output: \n";
    std::cout<<"func: "<<t.func<double>()<<std::endl;
    std::cout<<"get: "<<t.get()<<std::endl;
    std::cout<<"add: "<<t.add<double>(0)<<std::endl;
    std::cout<<"operator<< output: \n";
    std::cout<<str(t)<<std::endl;

    return 0;
}

I have compiled whithout std::string str(TestClass<T> f) function and its usage within the main and I observe the desired behaberou. However, I cannot compile this code with the following error:

error: expected primary-expression before '>' token
    out << f.func<T>();
                   ^ 
expected primary-expression before ')' token
    out << f.func<T>();
                     ^
expected primary-expression before '>' token
    out << f.add<T>(0.0);
                  ^

The compiler also produces errors regarding the << operator and the fact that f.func<T>() and f.add<T> type has not been resolved. If I remove the templated parts in the calls within str():

template<typename T>
std::string str(TestClass<T> f)
{
    std::ostringstream out;
    out << f.func();
    out << "\n";
    out << "get: ";
    out << f.get();
    out << "\n";
    out << f.add(0.0);
   return out.str();
}

Then, the compiler error is:

no matching function for call to 'TestClass<double>::func()'
     out << f.func();
         ^
candidate is:template<class N> N TestClass<T>::func() [with N = N; T = double]
     N func() {
       ^
couldn't deduce template parameter 'N'
    out << f.func();
        ^

Which make sense because func() type can not be deduced. Also I have tryied, using f.func<T>() and f.add(0.0) but the error is simillar to the first one.

My question is: How should I do it so the compiler can do its job?

Upvotes: 0

Views: 55

Answers (1)

Khouri Giordano
Khouri Giordano

Reputation: 1461

The func template member function must be labeled as a template function when called:

f.template func<T>();

The template keyword is required to indicate the left angle bracket < is NOT a less-than operator. See this explanation of this use of the template keyword.

The add member function picks up its template type from the parameter:

f.add(0.0); // typename N = double

Upvotes: 5

Related Questions