Как решить constexpr вернуть ссылку или нет - PullRequest
5 голосов
/ 22 марта 2019

Если у вас есть функция, которая if constexpr () решает сделать одно или другое, как вернуть lvalue в одном случае и rvalue в другом случае?

Следующий пример не компилируется в первой строке использования, поскольку тип возвращаемого значения auto не является ссылкой:

static int number = 15;

template<bool getref>
auto get_number(int sometemporary)
{
    if constexpr(getref)
    {
        return number; // we want to return a reference here
    }
    else
    {
        (...) // do some calculations with `sometemporary`
        return sometemporary;
    }
}

void use()
{
    int& ref = get_number<true>(1234);
    int noref = get_number<false>(1234);
}

Ответы [ 2 ]

11 голосов
/ 22 марта 2019

как вернуть lvalue в одном случае и rvalue в другом случае?

Полагаю, вы можете попробовать с decltype(auto) и парой скобок

template<bool getref>
decltype(auto) get_number() // "decltype(auto)" instead of "auto"
{
    if constexpr(getref)
    {
        return (number); // not "number" but "(number)"
    }
    else
    {
        return 123123; // just a random number as example
    }
}
4 голосов
/ 22 марта 2019

std::ref, кажется, помогает мне:

#include <functional>
#include <iostream>

static int number = 15;

template<bool getref>
auto get_number()
{
    if constexpr(getref)
    {
        return std::ref(number); // we want to return a reference here
    }
    else
    {
        return 123123; // just a random number as example
    }
}

int main(int argc, char **argv)
{
    int& ref = get_number<true>();
    int noref = get_number<false>();

    std::cout << "Before ref " << ref << " and number " << number << std::endl;
    ref = argc;
    std::cout << "After ref " << ref << " and number " << number << std::endl;

    std::cout << "Before noref " << noref << " and number " << number << std::endl;
    noref = argc * 2;
    std::cout << "After noref " << noref << " and number " << number << std::endl;
}

Попробуйте онлайн!

Как и ожидалось, изменение ref изменяет number (а не noref), в то время как изменение noref ничего не меняет.

Так как поведение constexpr и шаблонное, возвращение std::ref из number заставляет его фактически сделать ссылку.

...