Question

I am struggling with some weird behaviour that I do not understand. Below I have a minimal testcase that reproduces my problem. X is a class that has move semantics. In the code below, I expect that X<false> f(std::move(t)); results in a call to the templated move constructor. However, this results in a call to the templated copy constructor. Except when I remove the third templated constructor, then everything works as expected:

template<bool C>
class X
{
public:
    X() {}
    X(const X& other) {}
    X(X&& other) {}

    template<bool C2>
        X(const X<C2>& other) {}  // This constructor is actually being called
    template<bool C2>
        X(X<C2>&& other) {}  // I expected this constructor to be called

    template<class F>
        X(F f) {}      // If this constructor is removed, the expected constructor is called, removing my confusion
};

void testX()
{
    X<true> t;
    X<false> f(std::move(t));
}

Is there a good reason why the const X<C2>& other variant is picked over X<C2>&& other, or is this a bug in Visual Studio 2013? If this is a bug, are there any ideas for working around this problem (other than removing the last templated constructor)?

Was it helpful?

Solution

I have submitted a bug report for Visual Studio 2013 at https://connect.microsoft.com/VisualStudio/feedback/details/814740/copy-constructor-chosen-over-move-constructor-when-another-constructor-is-introduced#

A workaround was reported there: Move the template X(F f) constructor above the other templated constructors, and then the correct move constructor is called.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top