enable_if似乎在一个类外面工作,但不在内部 [英] enable_if seems to work outside a class but not inside
问题描述
这里是我有点奇怪的代码:
Here is my somewhat odd code:
template <typename T&>
class A {
public:
void b(typename std::enable_if<!std::is_pointer<T>::value, T>;::type o) {}
void b(typename std::enable_if<std::is_pointer<T>::value, T>;::type o) {}
};
template <typename T>
void b(typename std::enable_if<!std::is_pointer<T>::value, T>::type o) {}
template <typename T>
void b(typename std::enable_if<std::is_pointer<T>::value, T>::type o) {}
如果I ifdef
,则输出方法 b
,然后调用 b
pi
是 int *
,一切都编译。
If I ifdef
out the method b
and call b<int *>(pi
) where pi
is int *
, everything compiles.
如果我 ifdef
出函数 b
(外部类)并调用 A
If I ifdef
out the function b
(outside class) and call A<int *> a; a.b(pi)
, I get the following error:
命名为'type'in'std :: __ 1 :: enable_if< false,int *>'
为什么不一致,如何解决这个问题,以便我可以使用A中的方法?
Why the inconsistency and how can I fix the problem so that I can use the methods in A?
推荐答案
问题是,SFINAE只在重载解析时才起作用,只有函数模板。在您的方法案例中,整个类是一个模板,这意味着没有模板参数的替换(请记住:SFINAE ==
The problem is, that SFINAE only works during overload resolution and only if the function itself is a template. In your method case, the whole class is a template, meaning that there is no substitution of the template parameter (remember: SFINAE == "Substitution Failure Is Not An Error").
在实例化时,方法签名看起来像这样(永远不会调用它们):
At the point of instantiation, the method signatures look like this (nevermind the call to them):
void A<int*>::b(std::enable_if<false, int*>::type o) // error
void A<int*>::b(std::enable_if<true, int*>::type o)
为了解决这个问题,还要创建方法模板:
To fix this, make the methods templates too:
template<class T>
class A{
public:
template<class U>
void b(U o, typename std::enable_if<!std::is_pointer<U>::value>::type* = 0){}
// same for the other version
};
另一方面,让模板参数被推导是更好的方式使用SFINAE,应该修改自由函数,使其看起来像这样:
On a side note, letting the template argument get deduced is the better way to use SFINAE, so you should modify the free functions to look like this:
template<class T>
void b(T o, typename std::enable_if<!std::is_pointer<T>::value>::type* = 0){}
// same for the other version
在C ++ 11中,您甚至可以使用SFINAE的模板参数:
In C++11, you can even use the template parameters for SFINAE:
template<class T, EnableIf<std::is_pointer<T>> = {}>
void b(T o);
使用从这里:
namespace detail{ enum class enabler{}; }
template<class Cond, class T = detail::enabler>
using EnableIf = typename std::enable_if<C::value, T>::type;
这篇关于enable_if似乎在一个类外面工作,但不在内部的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!