如何enable/disable一个成员函数根据其存在的成员派生class?
How to enable/disable a member function according to the existence of a member of its derived class?
我搜索了 10 多个答案,没有一个符合我目前的情况。
(member detector marcos 来自: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(); }
};
预期:模板根据我在子类中的constexpr生成一组函数。
现实:产生一堆错误,一直没有编译成功...
有没有人知道是否可以在 C++17 中执行此操作?
编辑:“其他”在我的情况下是否可行?
这其实也是我的初衷。
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";
}
};
您需要 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";
}
};
请注意,如果两者同时为真,您将有歧义调用。
在 C++17 中,您可以使用 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 将允许在其 requires
:
中使用 class 模板参数
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";
}
};
请注意,如果两者同时为真,您将有歧义调用。
仅供参考,您可以在 C++17 中使用更简单的检测器:
#define CREATE_MEMBER_DETECTOR(X) \
template <typename T, typename = void> \
struct Detect_ ## X : std::false_type {}; \
\
template <typename T>\
struct Detect_ ## X<T, std::void_t<decltype(T::X)> > \
: std::true_type {};
我搜索了 10 多个答案,没有一个符合我目前的情况。
(member detector marcos 来自: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(); }
};
预期:模板根据我在子类中的constexpr生成一组函数。
现实:产生一堆错误,一直没有编译成功...
有没有人知道是否可以在 C++17 中执行此操作?
编辑:“其他”在我的情况下是否可行? 这其实也是我的初衷。
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";
}
};
您需要 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";
}
};
请注意,如果两者同时为真,您将有歧义调用。
在 C++17 中,您可以使用 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 将允许在其 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";
}
};
请注意,如果两者同时为真,您将有歧义调用。
仅供参考,您可以在 C++17 中使用更简单的检测器:
#define CREATE_MEMBER_DETECTOR(X) \
template <typename T, typename = void> \
struct Detect_ ## X : std::false_type {}; \
\
template <typename T>\
struct Detect_ ## X<T, std::void_t<decltype(T::X)> > \
: std::true_type {};