tags:

views:

86

answers:

3

Hello

I'm coming back to C++ after long years spent on other technologies and i'm stuck on some weird behavior when calling some methods taking std::string as parameters :

An example of call : LocalNodeConfiguration *LocalNodeConfiguration::ReadFromFile(std::string & path) { // ... throw configuration_file_error(string("Configuration file empty"), path); // ... }

When I compile I get this (I cropped file names for readability) :

/usr/bin/g++    -g -I/home/shtong/Dev/OmegaNoc/build -I/usr/share/include/boost-1.41.0   -o CMakeFiles/OmegaNocInternals.dir/configuration/localNodeConfiguration.cxx.o -c /home/shtong/Dev/OmegaNoc/source/configuration/localNodeConfiguration.cxx
    .../localNodeConfiguration.cxx: In static member function ‘static OmegaNoc::LocalNodeConfiguration* OmegaNoc::LocalNodeConfiguration::ReadFromFile(std::string&)’:
    .../localNodeConfiguration.cxx:72: error: no matching function for call to ‘OmegaNoc::configuration_file_error::configuration_file_error(std::string, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)’
    .../configurationManager.hxx:25: note: candidates are: OmegaNoc::configuration_file_error::configuration_file_error(std::string&, std::string&)
    .../configurationManager.hxx:22: note:                 OmegaNoc::configuration_file_error::configuration_file_error(const OmegaNoc::configuration_file_error&)

So as I understand it, the compiler is considering that my path parameter turned into a basic_string at some point, thus not finding the constructor overload I want to use. But I don't really get why this transformation happened.

Some search on the net suggested me to use g++ but I was already using it. So any other advice would be appreciated :)

Thanks

+3  A: 

The problem here is that the first (okay, well both, but the first is the one causing the problem) parameter to the configuration_file_error constructor is a non-const reference, and you can't bind a temporary object (like the one you're trying to pass in) to a non-const reference.

The constructor should probably take const references if it doesn't need to modify the strings. Since you're throwing it as an exception, I hope it doesn't really need to modify its parameters because the objects they refer to are probably going to be destroyed when the stack is unwound!

Nick Meyer
+12  A: 

The problem is not basic_string, because basic_string<char, restOfMess> is equivalent to string.

The problem is the function only provides

f(string&, string&) {
//------^

but you are calling as

 f(string("blah"), path);
// ^^^^^^^^^^^^^^

This is a rvalue (temporary object), and a rvalue cannot be bound to a mutable reference. You either need to change the prototype to accept const references or just pass-by-value:

    f(const string&, string&) {
//----^^^^^^
or
    f(string, string&) {

Or provide a mutable reference (if you really need to modify the 1st argument in that function):

string s = "blah blah blah";
f(s, path);
KennyTM
The funny thing about the internet resources saying to "use g++" is that MSVC detects this and displays a readable warning appropriately. *sigh* +1
Billy ONeal
That fixed it (changed the parameter types to const)So yeah I guess I underestimated the importance of the const keyword for the caller. And also underestimated the weirdness of the compiler messages (they were actually truly misleading...)Thank you all !
Shtong
A: 

string is just an alias for basic_string<>. From the standard (§21.2) which is undoubtedly copied directly into your header files,

typedef basic_string<char> string;

where basic_string<char> gains two default arguments from

template<class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> > class basic_string;

These arguments are somewhat arcane and won't ever change unless you manually override them.

(basic_string<wchar_t> is a distinct type which you might encounter with Unicode, however.)

Potatoswatter