views:

63

answers:

1

Hello everyone,

I am currently struggling to get the following code to compile. First the header file containing a class with a method template:

// ConfigurationContext.h

class ConfigurationContext
{
    public:
    template<typename T> T getValue(const std::string& name, T& default) const
        {
            ...
        }
}

Somewhere else I want to call this method like this:

int value = context.getValue<int>("foo", 5);

There I get the following error:

error: no matching function for call to 'ConfigurationContext::getValue(const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, int)'

I checked the obvious errors like missing includes and stuff like that. But everything seems to be right. I tried removing the pass-by-reference of the template type argument like this:

template<typename T> T getValue(const std::string& name, T default) const ...

Then it compiles without any errors and also runs fine, but I'd still like to pass in a reference here...

Does anybody know whats happening here and how to make this work?

+4  A: 

5 is a literal, and you cannot bind literals to non-const references. Either take T per copy or per const reference:

template<typename T> T getValue(const std::string& name, const T& def) const

(BTW, I doubt that your compiler accepts T default, because default is a keyword and must not be used as an identifier.)

The reason you cannot do this is because taking arguments per non-const reference usually implies that the callee might change the value and such changes should reflect at the caller's. (See How to pass objects to functions in C++?) However, you cannot change literals or temporaries. So you are not allowed to pass them to non-const references.

sbi
Of course, that makes sense now... I should probably not code anymore at this time (2:46 CEST). Thanks for this quick help! (Oh and I don't actually use T default in my code, just shortened everything to make it more clear...)
Simon Lehmann
I am wondering why the compiler can't give a meaningful message in this case.
Chubsdad
@chubsdad: C++ is a such wicked language to parse, implementers are pretty busy trying to make their compilers accept _valid_ code and making the right guesses about what went wrong in case of invalid code takes time. (Comeau, probably the most standard-conforming compiler, also comes with very good error messages.) And, for C++ standards, this error message isn't all that bad. At least it's not really _misleading_. (Remove the semicolon at the end of the declaration of a class which is the last thing in some header if you want to see an error message that's misleading for newbies.)
sbi