简体   繁体   中英

Any potential problem with using std::is_same_v rather than overload or specialization?

For example, I've got this:

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

Now let's assume that it makes sense to put these create s together, so I rewrite the code:

// 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"}; }

Or even:

// 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);
    }
}

I wanna to know is there any difference between these codes, or is it just about code style.

There are semantic differences between these. You can't use the Code A functions in generic algorithms like in this example:

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

Therefore I would prefere Code B over Code A.

The constexpr if is useful if you need to take a different route in generic algorithms. It saves you from creating an overloaded helper function or worse constructs.

An example would be to take a different route for void over other datatypes because you can not pass void as a parameter to a function. Suppose you take a function and want to set the value of a std::promise to the result. This function might not return a value, but you still want to execute the function. In this case the constexpr if will save you from a lot of headache and template metaprogramming.

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();
    }
}

It depends on your use case. if constexpr is limited to function scope, meaning you can't define your create function for Foo in foo.h and Bar in bar.h , so you have to include both.

This is not a criticism of if constexpr , as it is incredible useful in keeping related generic code brief and in one place.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM