Question

Is there a way to define a function which handle only xvalue or prvalue (or is here a exclusive or) ?

For instance suppose I have a method f(foo&& f), how can I declare f to bind xvalue type and reject prvalue type and vice versa ?

struct Foo{};
void xvalue(/*what put here ?*/){}
void prvalue(/*what put here ?*/){}

void main()
{
  Foo foo;

  prvalue(Foo());//compile
  prvalue(std::move(foo)));//fail at compilation

  xvalue(std::move(foo)); //compile
  xvalue(Foo());//fail at compilation
}

Maybe by using std::enable_if and the fact that decltype(e) is a rvalue reference type for xvalues and non-reference type for prvalue ?

Was it helpful?

Solution

Using the code from this answer it should be trivial.

#include <type_traits>
#include <iostream>
#include <utility>

template <typename T>
bool is_xvalue()
{
    if (std::is_lvalue_reference<T>::value)
        return false;
    else if (std::is_rvalue_reference<T>::value)
        return true;
    return false;
}

template <typename T>
bool is_prvalue()
{
    if (std::is_lvalue_reference<T>::value)
        return false;
    else if (std::is_rvalue_reference<T>::value)
        return false;
    else
        return true;
    return false;
}

struct Foo {};

int main()
{
    std::cout << std::boolalpha;
    std::cout << is_prvalue<decltype(Foo())>() << "\n"; // true
    std::cout << is_prvalue<decltype(std::move(Foo()))>() << "\n"; // false
    std::cout << is_xvalue<decltype(Foo())>() << "\n"; // false
    std::cout << is_xvalue<decltype(std::move(Foo()))>() << "\n"; // true
    return 0;
}

Unfortunately, you have to explicitly instantiate the templates, or else it doesn't work for some reason.

struct Foo {};

template <typename T, typename = typename std::enable_if<is_prvalue<T>(), void>::type>
void prvalue(T&& t)
{
}

template <typename T, typename = typename std::enable_if<is_xvalue<T>(), void>::type>
void xvalue(T&& t)
{
}

prvalue<decltype(Foo())>(Foo());
// prvalue<decltype(std::move(Foo()))>(std::move(Foo())); - compile error
xvalue<decltype(std::move(Foo()))>(std::move(Foo()));
// xvalue<decltype(Foo())>(Foo()); - compile error
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top