If I have the following code, which is a struct with value templates,
enum FakeEnum
{
FakeNone,
Fake1,
Fake2,
Fake3,
Fake4,
Fake5,
Fake6,
Fake7,
Fake8,
Fake9,
Fake10,
Fake11,
Fake12,
Fake13,
Fake14,
Fake15,
Fake16,
Fake17,
// ...
Fake100,
};
template<FakeEnum FE>
struct FakeStruct
{
void FakeIt();
};
template<FakeEnum FE>
void FakeStruct<FE>::FakeIt()
{
std::cout << "void FakeStruct<" << FE << ">::FakeIt()";
}
template<>
void FakeStruct<Fake12>::FakeIt()
{
std::cout << "specialized on Fake12";
}
template<>
void FakeStruct<Fake14>::FakeIt()
{
std::cout << "specialized on Fake14";
}
template<>
void FakeStruct<Fake23>::FakeIt()
{
std::cout << "specialized on Fake23";
}
...
...but what I'd really like to write is something like
template<>
void FakeStruct<Fake12 || Fake13 || Fake14 or how do I do this???>::FakeIt()
{
std::cout << "specialized on Fake12, Fake13, and Fake14";
}
Is there some kind of SFINAE-ish way to write that FakeStruct<>::FakeIt()
specialization without repeating it for multiple enum values? Ideally without changing the original declaration/signature of FakeStruct
?
CodePudding user response:
Use requires
:
#include <iostream>
enum E {a, b, c, d};
template <E Value>
struct A
{
void foo()
{
std::cout << "0\n";
}
};
template <E Value> requires (Value == b || Value == c) // or `Value >= b && value <= c`
struct A<Value>
{
void foo()
{
std::cout << "1\n";
}
};
int main()
{
A<a>{}.foo(); // 0
A<b>{}.foo(); // 1
A<c>{}.foo(); // 1
A<d>{}.foo(); // 0
}
CodePudding user response:
I would use if constexpr, it is still meta template programming but looks a lot like normal c .
#include <type_traits>
#include <iostream>
enum class FakeEnum // <= don't forget class here
{
FakeNone,
Fake1,
Fake2,
Fake3,
Fake4,
Fake5
};
template<FakeEnum E>
void FakeIt()
{
// you now can make sprecializations using "if constexpr"
if constexpr ((E == FakeEnum::Fake2) || (E == FakeEnum::Fake3) || (E == FakeEnum::Fake4))
{
// functionality here or call another function if needed
std::cout << "2 Or 3 Or 4\n";
}
else
{
std::cout << "1 or 5\n";
}
}
int main()
{
FakeIt<FakeEnum::Fake1>();
FakeIt<FakeEnum::Fake5>();
FakeIt<FakeEnum::Fake3>();
return 0;
}