[英]`enable_if()` to disable static member function declaration of templated class
I'm trying to declare function in template class so that function declaration depends on a template type argument.我正在尝试在模板 class 中声明 function ,以便 function 声明取决于模板类型参数。
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);
....
};
So I want to have, say, Block<uint16_t>
and Block<std::string>
and parse()
is declared as:所以我想拥有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);
But I'm getting error: 'enable_if' cannot be used to disable this declaration...typename std::enable_if<:std::is_class<T>:,value: T>:;type value);
但我收到错误: 'enable_if' cannot be used to disable this declaration...typename std::enable_if<:std::is_class<T>:,value: T>:;type value);
Could you help me to properly declare functions?你能帮我正确声明函数吗?
thanks.谢谢。
Enable_if only works in deduced contexts. Enable_if 仅适用于推断的上下文。 In your example, the deduction is done at class type time.在您的示例中,扣除是在 class 类型时间完成的。 By the time you get to the functions, T is already known, so there isn't anything to deduce.当你得到函数的时候,T 已经知道了,所以没有什么可以推导出来的。
You can make an otherwise superfluous template parameter, set its default type to T and then deduce on that.您可以制作一个多余的模板参数,将其默认类型设置为 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);
Your callers will never know that parse
actually has a template parameter, but now you can do all the fancy stuff on it.你的调用者永远不会知道parse
实际上有一个模板参数,但现在你可以在它上面做所有花哨的事情。
An alternative solution without SFINAE is to use tag dispatch:没有 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);
Note that in this solution, parse()
accepts any type S
, and if S
is not convertible into T
, the fail will occur inside parse()
itself.请注意,在此解决方案中, parse()
接受任何类型S
,如果S
不能转换为T
,则失败将发生在parse()
本身内部。 This can be too late, if parse()
itself is used for SFINAE.如果parse()
本身用于 SFINAE,这可能为时已晚。 For example, the following template:例如,以下模板:
template<class S, class T, typename = decltype(S::parse(0, std::declval<T>()))>
will result in a soft-fail (which is not an error) for the original parse()
and in a hard-fail (which is a compile error) for the proposed tag-dispatched version.将导致原始parse()
的软失败(这不是错误)和建议的标记分派版本的硬失败(这是一个编译错误)。 Thanks xaxxon for point out this difference.感谢xaxxon指出这种差异。
In C++20 with concepts, requires
will simplify things:在带有概念的 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> {... }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.