views:

49

answers:

2

Hello everyone :)

I have the following small code:

template <typename T>
class V
{
    public:
        T x;

    explicit V(T & _x)
    :x(_x){}

};

int main()
{
    V<float> b(1.0f); // fails
    return 0;
}

And it happens to fail. The message returned by g++ 4.4.5 is:

g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.d" -o"main.o" "../main.cpp"
../main.cpp: In function ‘int main()’:
../main.cpp:19: error: no matching function for call to ‘V<float>::V(float)’
../main.cpp:10: note: candidates are: V<T>::V(T&) [with T = float]
../main.cpp:6: note: V<float>::V(const V<float>&)

The thing is... whence the second constructor came? I really have no clue...

+5  A: 

Other answers discuss why you're getting a compile-time failure (which is what most questions are about when such failures are the most prominent part of the question). However. regarding your explicit question, "whence the second constructor came?":

12.8/4 "Copying class objects" of standard says:

If the class definition does not explicitly declare a copy constructor, one is declared implicitly.

If you'd like to avoid the implicit copy-ctor from being used, one of a few 'non-copyable' idioms can be used (such as boost::noncopyable): http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-copyable_Mixin

Michael Burr
This. The compiler does it for you. Default constructor and a copy constructor are supplied.
nakiya
@user this is why GCC says "candidate". Candidates are all constructors, but "viable candidates" are only the ones that could actually accept the argument.
Johannes Schaub - litb
+3  A: 

Compiler has supplied a copy constructor and assignment operator to your class. It is trying to match that copy constructor with your statement in main. The problem with this code is that in the constructor of class V you are taking the parameter as a non-const reference. When you do V<float> b(1.0f), compiler will create an unnamed temporary variable of type float for the value 1.0f. However, this unnamed temporary can not be bound to a non-const reference, it can be bound only to a const reference. Hence you need to change the constructor signature to explicit V(const T & _x).

Naveen