许多嵌套std :: conditional_t的替代方法?

时间:2018-08-30 07:42:50

标签: c++ templates typetraits if-constexpr

我发现许多嵌套的std :: conditional_t很难读取,因此我选择了其他模式(在具有自动返回类型的函数上调用decltype):

template<bool is_signed, std::size_t has_sizeof>
auto find_int_type(){
    static_assert(sizeof(int)==4);
    if constexpr(is_signed){
        if constexpr(has_sizeof==4){
            return int{};
        } else if constexpr (has_sizeof==8){
            return std::int64_t{};
        } else {
            return;
        }
    } else {
        if constexpr(has_sizeof==4){
            return (unsigned int){};
        }
        else if constexpr (has_sizeof==8){
            return std::uint64_t{};
        } else {
            return;
        }
    } 
}

static_assert(std::is_same_v<int, decltype(find_int_type<true, 4>())>);
static_assert(std::is_same_v<unsigned int, decltype(find_int_type<false, 4>())>);
static_assert(std::is_same_v<void, decltype(find_int_type<false, 3>())>);
static_assert(std::is_same_v<void, decltype(find_int_type<false, 5>())>);
static_assert(std::is_same_v<std::int64_t, decltype(find_int_type<true, 8>())>);
static_assert(std::is_same_v<std::uint64_t, decltype(find_int_type<false, 8>())>);
static_assert(std::is_same_v<void, decltype(find_int_type<false, 9>())>);

我的问题是:

有更好的方法吗?

这样比std :: conditional_t编译慢(假设我需要实例化的类型比在本例中使用内置类型的实例要扩展得多)。

P.S。这是一个玩具示例,IRCode我将处理一些更复杂的类型。

2 个答案:

答案 0 :(得分:6)

我个人认为,这里最清晰的方法是“数据驱动”。将条件放在表中(写为类模板的特长),让编译器进行模式匹配以确定类型更短,更不易出错并且更易于阅读或扩展。

template<bool is_signed, std::size_t has_sizeof>
struct find_int_type_impl { using type = void; }; // Default case

template<> struct find_int_type_impl<true,  4> { using type = std::int32_t;  };
template<> struct find_int_type_impl<true,  8> { using type = std::int64_t;  };
template<> struct find_int_type_impl<false, 4> { using type = std::uint32_t; };
template<> struct find_int_type_impl<false, 8> { using type = std::uint64_t; };

template<bool is_signed, std::size_t has_sizeof>
using find_int_type = typename find_int_type_impl<is_signed, has_sizeof>::type;

答案 1 :(得分:1)

由于std::disjunction<Args...>继承自Args...value的{​​{1}}中的第一个类型,或者,如果不存在这样的类型,则为true中的最后一个类型,我们可以使用它来产生多路分支:

Args...