1

Edit Updated Code:

class Any
{
public:
    Any()
    {
    }

    Any(const Any &other)
    {

    }

    Any(Any &other) // added per Ben's answer
    {
    }

    Any(Any &&other)
    {
    }

    Any(const char *value)
    {
    }

    template<typename T>
    Any(const T &value)
    {
    }

    template<typename T>
    Any(T &&value)
    {
        cout << "move ctor" << endl;
    }

    template<typename T>
    Any(const vector<T> &value)
    {
    }

    template<typename T>
    Any(vector<T> &&value)
    {
    }
};

int main(int argc, char *argv[])
{
    vector<string> numbers;
    numbers.push_back("one");
    numbers.push_back("two");
    numbers.push_back("three");
    numbers.push_back("four");

    Any anyNumbers(numbers);
    Any anyNumbersCopy = anyNumbers;

    return 0;
}


prints:

"move ctor"

Why is this happening?

Is there any way to force the default copy constructor to be called instead of the templated const& constructor?

I would like to avoid making the template constructor explicit if possible so that I can still implicitly construct the class like this;

Any number = 5;
CuriousGeorge
  • 7,120
  • 6
  • 42
  • 74
  • 3
    Provide a SSCCE that exhibits the problem. Overloading prefers non-templates to templates. – Ben Voigt Jul 29 '13 at 22:47
  • 1
    And, there is no such thing as a "template copy constructor". Your template function defines a family of converting constructors, including a conversion from `const Any&`, but not a copy constructor. – Ben Voigt Jul 29 '13 at 22:48
  • You'll need a constructor for `Any&`, not `Any&&`, to help in your example. The template provides `Any&` due to reference-collapsing rules, and is **not** only used for moving. – Ben Voigt Jul 29 '13 at 23:06

1 Answers1

5

Perhaps your real code looks more like this?

class Any
{
public:
    Any(){}

    Any(const Any &other)
    {
    }

    template<typename T>
    Any(T &&other)
    {
    }
};

In this case, the template is a better match for Any& other (not const!). The solution then is to provide a non-const non-template copy constructor overload:

class Any
{
public:
    Any(){}

    Any(const Any &other)
    {
    }

    Any(Any &other)
    {
    }

    template<typename T>
    Any(T &&other)
    {
    }
};
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • This was it. Using the non const copy constructor does result in the correct behaviour. Now I am getting a compiler warning though: warning C4521: 'Any' : multiple copy constructors specified – CuriousGeorge Jul 29 '13 at 23:01
  • Section 12.8p4 of the Standard specifically allows having multiple forms of the copy constructor in a single class... I'd recommend disabling that warning. – Ben Voigt Jul 29 '13 at 23:04