我有一个Base-class和一个派生类。我想设计一个C类,当基类或派生对象被移交时,它会以不同的方式作出反应:
template<typename T>
class Base {};
class Derived: public Base<int>{}
template<typename T>
class C
{
public:
static int f(T&& arg) {return 1;};
};
// Specialize C, not the function
template<typename T>
class C<T>
{
public:
static int f(T&& arg) {return 2;};
};
template<typename T>
int function(T&& arg) {
return C<T>::f(std::forward<T>(arg));
}
int main()
{
std::cout << function(1) << std::endl;
std::cout << function(Base<float>()) << std::endl;
std::cout << function(Derived()) << std::endl;
}
这应该打印:
1
2
2
有没有办法可以通过专门使用类C
而不是函数来实现这一点。实际上我只是交出C型,一切都发生在我无法触及的范围内。
为了清楚起见,功能的实现可能看起来像那样但我无法说清楚。我所知道的只是f:int f(T&&)
的签名;而且我必须拥有一个具有该签名功能的C类。
答案 0 :(得分:2)
通过功能()的专业化:
示例代码优先:
template< class T >
struct Base
{};
struct Child : Base<int>
{ };
template<typename T>
class C1
{
public:
static int f(T&& arg) {return 1;}
};
template<typename T>
class C2
{
public:
static int f(T&& arg) {return 2;}
};
template<typename T>
typename std::enable_if< std::is_base_of<Base<int>, T>::value, int >::type function(T&& arg)
{
return C2<T>::f(std::forward<T>(arg));
}
template<typename T>
typename std::enable_if< !std::is_base_of<Base<int>, T >::value, int >::type function(T&& arg)
{
return C1<T>::f(std::forward<T>(arg));
}
int main()
{
std::cout << function(1) << std::endl;
std::cout << function(Base<int>()) << std::endl;
std::cout << function(Child()) << std::endl;
return 0;
}
为什么:
所以这里的分歧就是我写了两个版本的function()。函数()的返回类型看起来有点毛茸茸,但如果T具有Base&lt;的话,将编译第一个版本。 int&gt;作为基本类型。否则将使用第二个版本。
的std :: enable_if&LT;&GT;是一个很好的工具,如果不满足条件,会导致模板扩展失败。在这种情况下,如果T没有Base&lt;则导致模板扩展失败。 int&gt;作为基类。在模板扩展失败的情况下,编译器继续寻找将编译的另一个版本的function()。
C1和C2是两个不同的对象,如果T将Base作为子节点,则使用C2,否则使用C1。
通过C的专业化:
template< class BaseArgument >
Base< BaseArgument > get_Base_type_of( Base< BaseArgument >&& );
template< class T >
struct has_Base
{
typedef char yes;
typedef long no;
template< typename T1 >
static yes Check( decltype( get_Base_type_of( declval<T1>() ) )* );
template< typename T1 >
static no Check( ... );
static const bool value = sizeof( decltype( Check<T>(0) ) ) == sizeof( yes ) ;
};
template< typename T, typename Placeholder = void >
class C
{
public:
static int f(T&& arg) {return 1;};
};
template<typename T>
class C< T, typename std::enable_if< has_Base<T>::value >::type >
{
public:
static int f(T&& arg) {return 2;};
};