Why can't I use traits with forwarding references in C++?

我的梦境 提交于 2019-12-10 14:14:28

问题


I have the following test code.

See godbolt https://godbolt.org/z/fLRM8d for an executable example

template <typename T> struct Traits {
    static const bool value = false;
};

struct Zip{};
template <> struct Traits<Zip> {
    static const bool value = true;
};

template <typename E>
void Execute(E && e){
    static_assert(Traits<E>::value);
}

int main(){

    auto z = Zip();

    // Fails the static assertion with an lvalue
    Execute(z);

    // Passes the static assertion with an rvalue
    Execute(Zip());
}

What is going on here that I can't use my type trait as I expect? What is the correct way to model this problem?


回答1:


There is a special rule regarding deduction of forwarding references in the Standard. Given a forwarding reference parameter T&&, T will be deduced as an lvalue reference if the function is called with an lvalue.

You need to take this into account in your traits:

Traits<std::remove_reference_t<E>>::value

live example on godbolt.org


From the Standard:

http://eel.is/c++draft/temp.deduct.call#3

A forwarding reference is an rvalue reference to a cv-unqualified template parameter that does not represent a template parameter of a class template (during class template argument deduction ([over.match.class.deduct])). If P is a forwarding reference and the argument is an lvalue, the type “lvalue reference to A” is used in place of A for type deduction.



来源:https://stackoverflow.com/questions/53742062/why-cant-i-use-traits-with-forwarding-references-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!