I had searched over 10 answers and nothing fits my current situation.
(member detector marcos comes from: http://en.wikibooks.org/wiki/More_C++_Idioms/Member_Detector)
CREATE_MEMBER_DETECTOR(normal);
CREATE_MEMBER_DETECTOR(abnormal);
template <typename T>
struct Weapon
{
//template <std::enable_if_t<Detect_normal<T>::value, T>* = nullptr>
template <std::enable_if_t<Detect_abnormal<T>::value, bool> = true>
void DefaultShoot()
{
std::cout << "special\n";
}
template <std::enable_if_t<Detect_normal<T>::value, bool> = true>
void DefaultShoot()
{
std::cout << "general\n";
}
};
struct FOO : public Weapon<FOO>
{
static constexpr auto normal = 10;
virtual void Shoot() { DefaultShoot(); }
};
Expect: The template generates a set of functions according to what constexpr I have in my subclasses.
Reality: Generate a bunch of errors and never successfully compiled...
Did anyone have a clue whether doing this in C++17 is possible?
Edit: Does the "else" possible in my situation? This is actually my original intention.
template <typename T>
struct Weapon
{
template <std::enable_if_t<Detect_abnormal<T>::value, bool> = true>
void DefaultShoot()
{
std::cout << "special\n";
}
//template <std::enable_if_t<Detect_normal<T>::value, bool> = true>
#some magical "else" code if the one above is invalidated.
void DefaultShoot()
{
std::cout << "general\n";
}
};
You would need the template parameter from the method for SFINAE:
template <typename T>
struct Weapon
{
template <typename U = T, std::enable_if_t<Detect_abnormal<U>::value, bool> = true>
void DefaultShoot()
{
std::cout << "special\n";
}
template <typename U = T, std::enable_if_t<Detect_normal<U>::value, bool> = true>
void DefaultShoot()
{
std::cout << "general\n";
}
};
Notice that you will have ambiguous call if both are true at the same time.
As you are in C++17, you might use if constexpr
:
template <typename T>
struct Weapon
{
void DefaultShoot()
{
if constexpr (Detect_abnormal<T>::value) {
std::cout << "special\n";
} else if constexpr (Detect_normal<T>::value) {
std::cout << "general\n";
} // else {}
}
};
C++20 would allow to use class template parameter in its requires
:
template <typename T>
struct Weapon
{
void DefaultShoot() requires(Detect_abnormal<T>::value)
{
std::cout << "special\n";
}
void DefaultShoot() requires(Detect_normal<T>::value)
{
std::cout << "general\n";
}
};
Notice that you will have ambiguous call if both are true at the same time.