The title is pretty much self explanatory. Here is my situation:
#include <type_traits>
class C1{
enum{
c1 = 3
}
}
class C2{
enum{
c2 = 10
}
}
template<class C>
class C3{
void do_this();
void do_that();
void foo(){
if constexpr(std::is_enum<C::c1>::value){
do_this();
}
if constexpr(std::is_enum<C::c2>::value){
do_that();
}
}
}
If I'd try to compile this I'd get the error
error: type/value mismatch at argument 1 in template parameter list for ‘template<class _Tp> struct std::is_enum’
note: expected a type, got ‘typename C::c1’
error: type/value mismatch at argument 1 in template parameter list for ‘template<class _Tp> struct std::is_enum’
note: expected a type, got ‘typename C::c2’
So hence my question: is it possible to use std::is_enum
with unnamed enum
s?
CodePudding user response:
You can use decltype
to get the type associated with c1
and c2
and then use SFINAE as shown below . Demo:
struct C1{
enum{
c1 = 3
};
};
struct C2{
enum{
c2 = 10
};
};
template<class C>
class C3{
void do_this(){std::cout << "do this called" << std::endl;}
void do_that(){std::cout << "do that called " << std::endl;}
public:
//overload for calling do_this
template<typename T = C, std::enable_if_t<std::is_same_v<T, C1>, bool> = std::is_enum<decltype(T::c1)>::value >void foo()
{
do_this();
}
//overload for calling do_that
template<typename T = C, std::enable_if_t<std::is_same_v<T, C2>, bool> = std::is_enum<decltype(T::c2)>::value >void foo()
{
do_that();
}
//overload when none of the conditions are satisfied
template<typename... T>
void foo(T...)
{
std::cout <<"pack called " << std::endl;
}
};
int main()
{
C3<C1> c1;
c1.foo(); //calls do_this() using #1
C3<C2> c2;
c2.foo(); //calls do_that() using #2
C3<int> c3;
c3.foo(); //calls the pack version
}
This has the advantage that this will work with C 11 also as now you don't need to use if constexpr
. C 11 Demo
CodePudding user response:
You should probably name the them both the same thing so the template works with both of them:
#include <cstdio>
#include <type_traits>
struct C1 {
enum { c = 3 };
};
struct C2 {
static constexpr int c = 10;
};
template <class C>
void foo() {
if constexpr (std::is_enum_v<decltype(C::c)>) {
std::puts("::c is an enum");
} else {
std::puts("::c is not an enum");
}
}
int main() {
foo<C1>();
foo<C2>();
}