Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 许多嵌套std::conditional\u t的替代方案?_C++_Templates_Typetraits_If Constexpr - Fatal编程技术网

C++ 许多嵌套std::conditional\u t的替代方案?

C++ 许多嵌套std::conditional\u t的替代方案?,c++,templates,typetraits,if-constexpr,C++,Templates,Typetraits,If Constexpr,我发现许多嵌套的std::conditional\u很难阅读,因此我选择了不同的模式(对具有自动返回类型的函数调用decltype): 模板 自动查找int类型(){ 静态断言(sizeof(int)==4); 如果constexpr(已签名){ 如果constexpr(has_sizeof==4){ 返回int{}; }如果constexpr(has_sizeof==8),则为else{ 返回std::int64_{}; }否则{ 返回; } }否则{ 如果constexpr(has_size

我发现许多嵌套的std::conditional\u很难阅读,因此我选择了不同的模式(对具有自动返回类型的函数调用decltype):

模板
自动查找int类型(){
静态断言(sizeof(int)==4);
如果constexpr(已签名){
如果constexpr(has_sizeof==4){
返回int{};
}如果constexpr(has_sizeof==8),则为else{
返回std::int64_{};
}否则{
返回;
}
}否则{
如果constexpr(has_sizeof==4){
返回(无符号整数){};
}
如果constexpr(has_sizeof==8),则为else{
返回std::uint64_{};
}否则{
返回;
}
} 
}
静态断言(std::is_same_v);
静态断言(std::is_same_v);
静态断言(std::is_same_v);
静态断言(std::is_same_v);
静态断言(std::is_same_v);
静态断言(std::is_same_v);
静态断言(std::is_same_v);
我的问题是:

有更好的办法吗

这种编译方式比std::conditional_t慢(假设我需要实例化的类型比我在本例中只使用内置类型的情况下要扩展得多)


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

就我个人而言,我觉得这里最清晰的方法是“数据驱动”。将条件放在表中(作为类模板的专门化编写),并让编译器进行模式匹配以确定类型,这样做更短、更不容易出错,并且更易于阅读或扩展

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;
模板
结构find_int_type_impl{using type=void;};//默认情况
模板结构find_int_type_impl{using type=std::int32_t;};
模板结构find_int_type_impl{using type=std::int64_t;};
模板结构find_int_type_impl{using type=std::uint32_t;};
模板结构find_int_type_impl{using type=std::uint64_t;};
模板
使用find_int_type=typename find_int_type\u impl::type;

由于
std::disjunction
继承了
Args…
中的第一个类型,其
true
,或者如果不存在此类类型,则继承
Args…
中的最后一个类型,我们可以(ab)使用它来生成多路分支:

template<class... Args>
using select = typename std::disjunction<Args...>::type;

template<bool V, class T>
struct when {
    static constexpr bool value = V;
    using type = T;
};

template<bool is_signed, std::size_t has_sizeof>
using find_int_type = select<
    when<is_signed, select<
        when<has_sizeof==4, int>,
        when<has_sizeof==8, std::int64_t>,
        when<false, void>
    >>,
    when<!is_signed, select<
        when<has_sizeof==4, unsigned int>,
        when<has_sizeof==8, std::uint64_t>,
        when<false, void>
    >>
>;
模板
使用select=typename std::disjunction::type;
模板
结构时{
静态constexpr布尔值=V;
使用类型=T;
};
模板
使用find_int_type=select<
当>,
什么时候
什么时候
什么时候
>>
>;

不是您的问题的答案,但您可以替换
return\u void()通过
返回void()-少一个实现细节,如果没有其他内容,则返回也很好。
如果constexpr
,如果有的话,编译速度应该比任何专业化或基于SFINAE的方法都快得多。在这种情况下,这是非常好的,但是如果条件是一些复杂的constexpr bool返回函数呢?@nosenseal-显然没有一刀切的方法。我真的无法评论如此模糊的标准。这只是一个你没有提到的替代方案,所以我觉得它值得作为一个选项添加。
template<class... Args>
using select = typename std::disjunction<Args...>::type;

template<bool V, class T>
struct when {
    static constexpr bool value = V;
    using type = T;
};

template<bool is_signed, std::size_t has_sizeof>
using find_int_type = select<
    when<is_signed, select<
        when<has_sizeof==4, int>,
        when<has_sizeof==8, std::int64_t>,
        when<false, void>
    >>,
    when<!is_signed, select<
        when<has_sizeof==4, unsigned int>,
        when<has_sizeof==8, std::uint64_t>,
        when<false, void>
    >>
>;