Любая потенциальная проблема с использованием std :: is_same_v вместо перегрузки или специализации? - PullRequest
3 голосов
/ 25 марта 2020

Например, у меня есть это:

// Code A
int create_int() { return 42; }
double create_double() { return 3.14; }
std::string create_string() { return {"Hi"}; }

Теперь давайте предположим, что имеет смысл соединить эти create вместе, поэтому я переписываю код:

// Code B
template <typename T> T create();
template <> int create<int>() { return 42; }
template <> double create<double>() { return 3.14; }
template <> std::string create<std::string>() { return {"Hi"}; }

Или даже:

// Code C
#include <type_traits>

template <typename T> T create()
{
    if constexpr (std::is_same_v<T, int>)
    {
        return 42;
    }
    else if constexpr (std::is_same_v<T, double>)
    {
        return 3.14;
    }
    else if constexpr (std::is_same_v<T, std::string>)
    {
        return {"Hi"};
    }
    else
    {
        // static_assert(false);
        return static_cast<T>(0);
    }
}

Я хочу знать, есть ли разница между этими кодами или это просто стиль кода.

Ответы [ 2 ]

1 голос
/ 25 марта 2020

Есть семанти c различий между ними. Вы не можете использовать функции Code A в обобщенных c алгоритмах, как в этом примере:

template <class T>
T generic_function() {
    return create<T>();
}

Поэтому я бы предпочел код B над кодом A.

Constexpr if is полезно, если вам нужно выбрать другой маршрут в обобщенных c алгоритмах. Это избавляет вас от создания перегруженной вспомогательной функции или худших конструкций.

Примером может быть использование другого маршрута для void для других типов данных, поскольку вы не можете передать void в качестве параметра функции. Предположим, вы берете функцию и хотите установить значение std::promise для результата. Эта функция может не возвращать значение, но вы все равно хотите выполнить функцию. В этом случае constexpr if избавит вас от головной боли и шаблонного метапрограммирования.

template <class Fn>
void my_function(Fn fn) {
    std::promise<decltype(fn())> promise;

    if constexpr(!std::is_same_v<void, decltype(fn())>) {
        promise.set_value(fn());
    } else {
        fn();
        promise.set_value();
    }
}
0 голосов
/ 25 марта 2020

Это зависит от вашего варианта использования. if constexpr ограничен областью действия функции, то есть вы не можете определить свою create функцию для Foo в foo.h и Bar в bar.h, поэтому вы должны включить оба.

Это не критика if constexpr, так как она невероятно полезна для краткости и краткости связанного родового c кода.

...