lew*_*wis 7 c++ templates c++17 conditional-types
我很难理解如何阻止代码std::conditional_t在错误分支中被评估。
#include <type_traits>\n\nusing namespace std;\n\nnamespace {\n template <typename T>\n using BaseDifferenceType = decltype (T{} - T{});\n}\n\nint main ()\n{\n using T = int;\n static_assert(! is_enum_v<T>);\n BaseDifferenceType<T> xxx {};\n \n // PROBLEM IS HERE - though is_enum is false, we still evaluate underlying_type<T> and complain it fails\n using aaa = conditional_t<is_enum_v<T>, underlying_type_t<T>, BaseDifferenceType<T>>;\n \n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n您可以在https://www.onlinegdb.com/uxlpSWVXr在线尝试此操作。
\n编译(使用 C++17)给出错误:
\n#include <type_traits>\n\nusing namespace std;\n\nnamespace {\n template <typename T>\n using BaseDifferenceType = decltype (T{} - T{});\n}\n\nint main ()\n{\n using T = int;\n static_assert(! is_enum_v<T>);\n BaseDifferenceType<T> xxx {};\n \n // PROBLEM IS HERE - though is_enum is false, we still evaluate underlying_type<T> and complain it fails\n using aaa = conditional_t<is_enum_v<T>, underlying_type_t<T>, BaseDifferenceType<T>>;\n \n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n
答案很简单:
你不知道。
std::conditional_t始终具有三个完全评估的参数:
类似布尔值的参数和两种类型。
如果选择其中一个无法评估另一个,则需要使用自定义模板并对其进行适当的专门化:
template <class T, bool = std::is_enum_v<T>>
struct type_finder { using type = std::underlying_type_t<T>; };
template <class T>
struct type_finder<T, false> { using type = BaseDifferenceType<T>; };
template <class T>
using type_finder_t = typename type_finder<T>::type;
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用if constexpr自动返回类型扣除:
template <class T>
auto type_finder_f() {
if constexpr (std::is_enum_v<T>)
return std::underlying_type_t<T>();
else
return BaseDifferenceType<T>();
}
template <class T>
using type_finder_t = decltype(type_finder_f<T>());
Run Code Online (Sandbox Code Playgroud)
可能的替代方法是创建自定义类型特征,如下所示
template <template <typename...> class Cont, typename ... Ts>
struct LazyType
{ using type = Cont<Ts...>; };
Run Code Online (Sandbox Code Playgroud)
并重写你的std::conditional如下
using aaa = std::conditional_t<
std::is_enum_v<T>,
LazyType<underlying_type_t, T>,
LazyType<BaseDifferenceType, T>>::type;
// ............................................^^^^^^
Run Code Online (Sandbox Code Playgroud)
观察我添加了一个final ::type:它是所需类型的“构造函数”,完全避免了不需要的类型。
题外话未经请求的建议:避免
using namespace std;
Run Code Online (Sandbox Code Playgroud)
这被认为是不好的做法
| 归档时间: |
|
| 查看次数: |
661 次 |
| 最近记录: |