How to assign static constexpr field value based on template type

90 Views Asked by At

I'd like to assign static constexpr field of a class based on template type. I've found out below solution but I guess it is not best solution especially if there are other types to support. Maybe some kind of constexpr map? (I can use STL and/or boost)

#include <iostream>
#include <string_view>

template <typename T>
struct Example
{
    static constexpr std::string_view s{std::is_same_v<T, int> ? "int" 
         : (std::is_same_v<T, double> ? "double" : "other")};
};


int main()
{
    const Example<int> example;
    std::cout << example.s << std::endl;
    return 0;
}

2

There are 2 best solutions below

3
463035818_is_not_an_ai On BEST ANSWER

You can write a trait

template <typename T> 
struct st { };

and specialize it accordingly:

template <> struct st<int> { static constexpr std::string_view value{"int"}; }
// ... other types

then use it:

template <typename T>
struct Example
{
    static constexpr std::string_view s = st<T>::value;
};

Alternatively you could write a function that utilizes a series of constexpr if to return the right string for given type. Though, I wouldn't expect this to be cleaner or more readable.

3
Pepijn Kramer On

Another option is to use constepxr function specialization instead of specializing a struct. That also allows you to detect unsupported types if you want to.

#include <string_view>
#include <type_traits>
#include <iostream>

namespace details
{

template<typename type_t>
inline constexpr std::string_view as_string()
{
    // example of how to alert at compile time an "other" type is encountered
    static_assert(!std::is_same_v<type_t,type_t>, "unsupported type");
    return "other";
}

// provide specializations for the types you want to support
template<> inline constexpr std::string_view as_string<int>(){ return "int"; }
template<> inline constexpr std::string_view as_string<double>(){ return "double"; }

}

template<typename type_t>
struct Example
{
    static constexpr std::string_view s{details::as_string<type_t>()};
};

int main()
{
    constexpr Example<int> example;
    static_assert(example.s == "int");

    //constexpr Example<char> example_fail; <== this will now not compile with error : static_assert failed: 'unsupported type' 
}