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?
You can use decltype
to get the type associated with c1
and c2
and then use SFINAE as shown below . C++11 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,typename std::enable_if<std::is_same<T, C1>::value, bool>::type = std::is_enum<decltype(T::c1)>::value >void foo()
{
do_this();
}
//overload for calling do_that
template<typename T = C,typename std::enable_if<std::is_same<T, C2>::value, bool>::type = 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 <<"ellipsis 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 ellipsis version
}
See also C++ 17 demo version that uses std::enable_if_t
and std::is_same_v
and std::is_enum_v
.
struct C1{
enum{
c1 = 3
};
};
template<typename T>
concept enumC1 = std::is_same_v<T, C1>;
struct C2{
enum{
c2 = 10
};
};
template<typename T>
concept enumC2 = std::is_same_v<T, C2>;
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 when none of the conditions are satisfied
template<typename T = C>
void foo()
{
std::cout <<"general called " << std::endl;
}
//overload for calling do_this
template<enumC1 T = C>void foo()
{
do_this();
}
//overload for calling do_that
template<enumC2 T = C>void foo()
{
do_that();
}
};
int main()
{
C3<C1> c1;
c1.foo(); //calls do_this()
C3<C2> c2;
c2.foo(); //calls do_that()
C3<int> c3;
c3.foo(); //calls the general version
}