我试图在模板类中声明函数,以便函数声明取决于模板类型参数。
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);
能帮我正确声明函数吗?
谢谢。
答案 0 :(得分:2)
Enable_if仅在推论的上下文中起作用。在您的示例中,推论是在类类型时间完成的。到您使用这些功能时,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
实际上有一个模板参数,但是现在您可以在上面做所有花哨的事情了。
答案 1 :(得分:1)
没有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
,则失败将发生在parse()
内部本身。如果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>
{ ... }