2013-04-09 108 views
36

我想专用一个函数模板,以便返回类型根据模板参数的类型而变化。覆盖函数模板专门化中的返回类型

class ReturnTypeSpecialization 
{ 
public: 
    template<typename T> 
    T Item(); 
}; 

// Normally just return the template type 
template<typename T> 
T ReturnTypeSpecialization::Item() { ... } 

// When a float is specified, return an int 
// This doesn't work: 
template<float> 
int ReturnTypeSpecialization::Item() { ... } 

这可能吗?我无法使用C++ 11。

+0

你想达到什么目的? – didierc 2013-04-09 20:37:52

+0

我想要一个函数来返回作为模板参数提供的类型,除非在特殊情况下我希望函数返回不同的类型。 – 2013-04-09 20:40:51

+0

只是为了记录:如果模板参数是从参数的类型中推导出来的,而不是明确指定的,则完成返回不同类型的更简单的方法是使用函数重载。 (当然这个例子在这个例子中不起作用,因为没有参数) – jorgbrown 2017-05-09 16:03:41

回答

38

由于专业化与返回类型的基本模板的同意,你可以通过添加一个“返回类型特征”做起来很,一个结构,你可以专注并从中汲取真正的返回类型:

// in the normal case, just the identity 
template<class T> 
struct item_return{ typedef T type; }; 

template<class T> 
typename item_return<T>::type item(); 

template<> 
struct item_return<float>{ typedef int type; }; 
template<> 
int item<float>(); 

Live example.

请注意,你可能要坚持以下,所以你只需要更新的返回类型在item_return专业化。

template<> 
item_return<float>::type foo<float>(){ ... } 
// note: No `typename` needed, because `float` is not a dependent type 
+1

+1我喜欢这个:P – Rapptz 2013-04-09 20:51:10

+2

确保所有的特化都在它们被实例化之前被声明。实际上,这意味着专业化必须在同一个头文件中声明,并且声明应该尽可能地接近。 – aschepler 2013-04-09 20:55:31

+0

@aschepler:非常好的一点。摆弄这种形式的专业化非常不稳定。 – Xeo 2013-04-09 20:57:36

4

你可以做模板特像这样:

template<typename T> 
T item() { 
    return T(); 
} 

template<> 
float item<float>() { 
    return 1.0f; 
} 
+2

这意味着'T'也是总是返回类型,从问题的例子来看,似乎并不是这种情况。 – Xeo 2013-04-09 20:33:50

+0

@Zeta:你可以完全专注于它们(也称为* explicit specialization *)。 – Xeo 2013-04-09 20:34:33

+0

@Xeo:问题标题:*“ 覆盖功能模板专业化中的返回类型 ”*。可能是问题内容中的拼写错误。 – Zeta 2013-04-09 20:34:59

4

也许你可以使用下面的技巧。鉴于这些简单的类型特点:

template<bool b, typename T, typename U> 
struct conditional { typedef T type; }; 

template<typename T, typename U> 
struct conditional<false, T, U> { typedef U type; }; 

template<typename T, typename U> 
struct is_same { static const bool value = false; }; 

template<typename T> 
struct is_same<T, T> { static const bool value = true; }; 

你可以写出如下类和专业的成员函数:

class ReturnTypeSpecialization 
{ 
public: 
    template<typename T> 
    typename conditional<is_same<T, float>::value, int, T>::type 
    Item(); 
}; 

// Normally just return the template type 
template<typename T> 
typename conditional<is_same<T, float>::value, int, T>::type 
ReturnTypeSpecialization::Item() { return T(); } 

// When a float is specified, return an int 
template<> 
int ReturnTypeSpecialization::Item<float>() { return 1.0f; } 

简单的测试程序(使用C++ 11只是为了验证):

int main() 
{ 
    ReturnTypeSpecialization obj; 
    static_assert(std::is_same<decltype(obj.Item<bool>()), bool>::value, "!"); 
    static_assert(std::is_same<decltype(obj.Item<float>()), int>::value, "!"); 
} 

这是live example

+0

他没有C++ 11。 – Rapptz 2013-04-09 20:47:50

+0

@Rapptz:好的,对不起,我错过了。但我相信这可以重写,而不使用任何C++ 11功能('std :: conditional'不难重写) – 2013-04-09 20:49:31

+0

我认为你的错误处理方式是错误的。此外,这是一个很好的模板,可以扩展到更多的专业领域,更糟糕的是,所有的专业领域都必须事先知道。 – Xeo 2013-04-09 20:54:21

2

做一个工人类的所有专业化,并使用一个简单的函数作为包装将隐含专门化。

#include <iostream> 
using std::cout; 

// worker class -- return a reference to the given value 
template< typename V > struct worker 
    { 
    typedef V const & type; 
    static type get(V const & v) { return v; } 
    }; 

// worker class specialization -- convert 'unsigned char' to 'int' 
template<> struct worker<unsigned char> 
    { 
    typedef int type; 
    static type get(unsigned char const & v) { return v; } 
    }; 

// mapper function 
template< typename V > typename worker<V>::type mapper(V const & v) 
    { 
    return worker<V>::get(v); 
    } 

int main() 
    { 
    char a='A'; 
    unsigned char b='B'; 
    cout << "a=" << mapper(a) << ", b=" << mapper(b) << "\n"; 
    } 

在这个例子中,unsigned char专业化导致它被转换为int,使得cout将其显示为一个数而不是作为一个字符,产生以下输出...

a=A, b=66 
+0

这与@ Xeo的答案具有相同的基本机制,但由于只需要一个专业化,所以可能会被认为有点清洁。实施的另一个特点是,正常情况基本上是一个NOP - 它只是返回一个对原始值的引用。 – nobar 2014-01-23 05:27:25

+0

我也喜欢这个解决方案。如果你想特别禁止通用的解决方案,只允许显式模板,第一个结构可以改变为'template struct worker;',没有主体。 – Eyal 2017-12-19 07:39:18