Jos*_*eno 3 c++ enums types constraints type-traits
标题几乎是不言自明的。这是我的情况:
\n#include <type_traits>\n\nclass C1{\n enum{\n c1 = 3\n }\n}\n\nclass C2{\n enum{\n c2 = 10\n }\n}\n\ntemplate<class C>\nclass C3{\n void do_this();\n void do_that();\n\n void foo(){\n if constexpr(std::is_enum<C::c1>::value){\n do_this();\n }\n if constexpr(std::is_enum<C::c2>::value){\n do_that();\n }\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n如果我尝试编译它,我会收到错误
\nerror: type/value mismatch at argument 1 in template parameter list for \xe2\x80\x98template<class _Tp> struct std::is_enum\xe2\x80\x99\nnote: expected a type, got \xe2\x80\x98typename C::c1\xe2\x80\x99\n\nerror: type/value mismatch at argument 1 in template parameter list for \xe2\x80\x98template<class _Tp> struct std::is_enum\xe2\x80\x99\nnote: expected a type, got \xe2\x80\x98typename C::c2\xe2\x80\x99\n
Run Code Online (Sandbox Code Playgroud)\nstd::is_enum
因此我的问题是:是否可以与未命名的一起使用enum
?
绝对可以std::is_enum
与未命名的枚举一起使用。
当前的实现中只有 2 个问题需要解决:
std::is_enum<C::c1>::value
-C::c1
是数据成员,但std::is_enum
需要类型模板参数。decltype(...)
,例如std::is_enum<decltype(C::c1)>::value
C::c1
C
如果没有名为 的成员,将导致替换失败c1
。所以对于 C++20 这可以工作:
template<class T>
concept is_enum_value = std::is_enum_v<T>;
template<class C>
struct C3 {
void foo() {
if constexpr(requires { { C::c1 } -> is_enum_value; }) {
do_this();
}
if constexpr(requires { { C::c2 } -> is_enum_value; }) {
do_that();
}
}
// ...
};
Run Code Online (Sandbox Code Playgroud)
如果C::c1
和C::c2
是互斥的(即每个类都C
具有其中之一c1
或c2
两者都不存在 - 但绝不会同时c1
存在两者),您可能会考虑使用尾随的 require 子句进行重载。c2
foo
template<class C>
struct C3 {
void foo() requires requires { { C::c1 } -> is_enum_value; } {
// do_this implementation
}
void foo() requires requires { { C::c2 } -> is_enum_value; } {
// do_that implementation
}
};
Run Code Online (Sandbox Code Playgroud)
如果 C++20 不可用,您需要使用 SFINAE,这有点麻烦:
template<class T, class = void>
constexpr bool has_c1 = false;
template<class T>
constexpr bool has_c1<T, std::enable_if_t<std::is_enum_v<decltype(T::c1)>>> = true;
template<class T, class = void>
constexpr bool has_c2 = false;
template<class T>
constexpr bool has_c2<T, std::enable_if_t<std::is_enum_v<decltype(T::c2)>>> = true;
template<class C>
struct C3 {
void foo() {
if constexpr(has_c1<C>) {
do_this();
}
if constexpr(has_c2<C>) {
do_that();
}
}
// ...
};
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
391 次 |
最近记录: |