开发者

Why in C++0x, the compiler chooses the generic move assignment over the specific one?

I have the following code:

#include <iostream>
using namespace std;

template <class T> class Foo {
public:
    template <class U> void operator = (const U &u) {
        cout << "generic copy assigment\n";
    }

    void operator = (const Foo<T> &f) {
        cout << "specific copy assigment\n";
    }

    template <class U> void operator = (U &&u) {
        cout << "generic move assigment\n";
    }

    void operator = (Foo<T> &&f) {
        cout << "specific move assigme开发者_开发问答nt\n";
    }
};

int main() {
    Foo<int> i, j;
    i = j;
    return 0;
}

If this runs, it prints "generic move assignment", i.e. the compiler prefers the move over the copy. However, if I comment out the two move assignments:

template <class T> class Foo {
public:
    template <class U> void operator = (const U &u) {
        cout << "generic copy assigment\n";
    }

    void operator = (const Foo<T> &f) {
        cout << "specific copy assigment\n";
    }
};

the output is "specific copy assignment".

In other words, when the class is move-enabled, the generic move is selected over the specific one, whereas if the class is not move-enabled, the specific copy is selected over the generic one.

Is it a bug of Visual Studio 2010 or is this behavior defined in the c++0x specifications?


Your template is not a "generic move assignment". But it is a "perfect forwarder", except that in your case it doesn't forward. The rule in C++0x is that template argument deduction treats a parameter "T&&" specially: Lvalue arguments deduce T to ArgType&, and Rvalue arguments deduce it to ArgType. That way, an lvalue of type ArgType will yield to ultimate parameter type ArgType&, and an Rvalue will ultimately yield to ArgType&&.

In your case, the lvalue right hand side yields a deduced parameter type "Foo &", which perfectly well matches the lvalue argument.

The currently draft (n3126) forbids the compiler to use the template to perform the copy assignment (in a very confusingly worded paragraph), though. It depens on the resolution of issue 1080 whether that will change or not.


#include <iostream>
using namespace std;

template <class T> class Foo {
    public:
    template <class U> void operator = (const U &u) {
        cout << "generic copy assigment\n";
    }

    void operator = (const Foo<T> &f) {
        cout << "specific copy assigment\n";
    }

    template <class U> void operator = (U &&u) {
        cout << "generic move assigment\n";
    }

//    void operator = (Foo<T> &&f) {
//        cout << "specific move assigment\n";
//    }
};

int main() {
    Foo<int> i, j;
    i = std::move(j);
    return 0;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜