`enable_if()` 禁用模板化的静态成员函数声明 class
`enable_if()` to disable static member function declaration of templated class
我正在尝试在模板中声明函数 class 以便函数声明取决于模板类型参数。
template<typename T>
struct Block
{
static bool parse(int32_t index,
const typename std::enable_if<std::is_class<T>::value, T>::type& value);
static bool parse(int32_t index,
typename std::enable_if<!std::is_class<T>::value, T>::type value);
....
};
所以我想 Block<uint16_t>
和 Block<std::string>
和 parse()
声明为:
bool parse(int32_t index, const std::string& value);
or
bool parse(int32_t index, uint16_t value);
但我收到错误消息:'enable_if' cannot be used to disable this declaration
...typename std::enable_if<!std::is_class<T>::value, T>::type value);
你能帮我正确声明函数吗?
谢谢。
Enable_if 仅适用于推断的上下文。在您的示例中,扣除是在 class 类型时间完成的。当你到达函数时,T 已经知道,所以没有什么可以推断的。
您可以创建一个多余的模板参数,将其默认类型设置为 T,然后据此进行推导。
template<typename T>
struct Block
{
// now parse has to deduce U
template<typename U=T>
static bool parse(int32_t index,
typename std::enable_if<!std::is_class<U>::value, T>::type value);
您的调用者永远不会知道 parse
实际上有一个模板参数,但现在您可以在其上做所有花哨的事情。
没有 SFINAE 的替代解决方案是使用标签调度:
template<typename S>
static bool parse(int32_t index, S&& value) {
return parse_impl(index, value, std::is_class<T>{});
}
private:
static bool parse_impl(int32_t index, const T& value, std::true_type);
static bool parse_impl(int32_t index, T value, std::false_type);
请注意,在此解决方案中,parse()
接受任何类型 S
,如果 S
无法转换为 T
,则会在 [=13] 内发生失败=] 本身。这可能为时已晚,如果 parse()
本身用于 SFINAE。例如,以下模板:
template<class S, class T, typename = decltype(S::parse(0, std::declval<T>()))>
将导致原始 parse()
的软失败(这不是错误)和建议的标签分派版本的硬失败(这是编译错误)。感谢 xaxxon 指出这个区别。
在带有概念的 C++20 中,requires
将简化事情:
static bool parse(int32_t index, const T& value)
requires std::is_class_v<T>
{ ... }
static bool parse(int32_t index, T value)
requires !std::is_class_v<T>
{ ... }
我正在尝试在模板中声明函数 class 以便函数声明取决于模板类型参数。
template<typename T>
struct Block
{
static bool parse(int32_t index,
const typename std::enable_if<std::is_class<T>::value, T>::type& value);
static bool parse(int32_t index,
typename std::enable_if<!std::is_class<T>::value, T>::type value);
....
};
所以我想 Block<uint16_t>
和 Block<std::string>
和 parse()
声明为:
bool parse(int32_t index, const std::string& value);
or
bool parse(int32_t index, uint16_t value);
但我收到错误消息:'enable_if' cannot be used to disable this declaration
...typename std::enable_if<!std::is_class<T>::value, T>::type value);
你能帮我正确声明函数吗?
谢谢。
Enable_if 仅适用于推断的上下文。在您的示例中,扣除是在 class 类型时间完成的。当你到达函数时,T 已经知道,所以没有什么可以推断的。
您可以创建一个多余的模板参数,将其默认类型设置为 T,然后据此进行推导。
template<typename T>
struct Block
{
// now parse has to deduce U
template<typename U=T>
static bool parse(int32_t index,
typename std::enable_if<!std::is_class<U>::value, T>::type value);
您的调用者永远不会知道 parse
实际上有一个模板参数,但现在您可以在其上做所有花哨的事情。
没有 SFINAE 的替代解决方案是使用标签调度:
template<typename S> static bool parse(int32_t index, S&& value) { return parse_impl(index, value, std::is_class<T>{}); } private: static bool parse_impl(int32_t index, const T& value, std::true_type); static bool parse_impl(int32_t index, T value, std::false_type);
请注意,在此解决方案中,
parse()
接受任何类型S
,如果S
无法转换为T
,则会在 [=13] 内发生失败=] 本身。这可能为时已晚,如果parse()
本身用于 SFINAE。例如,以下模板:template<class S, class T, typename = decltype(S::parse(0, std::declval<T>()))>
将导致原始
parse()
的软失败(这不是错误)和建议的标签分派版本的硬失败(这是编译错误)。感谢 xaxxon 指出这个区别。在带有概念的 C++20 中,
requires
将简化事情:static bool parse(int32_t index, const T& value) requires std::is_class_v<T> { ... } static bool parse(int32_t index, T value) requires !std::is_class_v<T> { ... }