在函数模板特化中覆盖返回类型

M. *_*ley 48 c++ templates

我想专门化一个函数模板,使返回类型根据模板参数的类型而改变.

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() { ... }
Run Code Online (Sandbox Code Playgroud)

这可能吗?我不能使用C++ 11.

Xeo*_*Xeo 51

由于专业化必须与返回类型的基本模板一致,您可以通过添加"返回类型特征",可以专门化的结构并从中绘制真实的返回类型来实现:

// 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>();
Run Code Online (Sandbox Code Playgroud)

实例.

请注意,您可能希望坚持以下内容,因此您只需要更新特化中的返回类型item_return.

template<>
item_return<float>::type foo<float>(){ ... }
// note: No `typename` needed, because `float` is not a dependent type
Run Code Online (Sandbox Code Playgroud)

  • 确保在实例化之前声明所有特化.实际上,这意味着必须在同一个头文件中声明专门化,并且声明应该尽可能地靠近. (2认同)
  • @didierc:嗯,C++中的依赖类型也可以依赖于一个值...如果它是一个依赖值.;)(非类型)模板参数,或者从模板参数派生的任何值.存在依赖类型,从属值和从属名称. (2认同)

Rap*_*ptz 8

您可以像这样进行模板专业化:

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

template<>
float item<float>() {
    return 1.0f;
}
Run Code Online (Sandbox Code Playgroud)

  • 这意味着“T”也是始终返回类型,从问题中的示例来看,情况似乎并非如此。 (4认同)

And*_*owl 5

也许你可以使用以下hack.鉴于这些简单的类型特征:

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; };
Run Code Online (Sandbox Code Playgroud)

您可以编写您的类和专用成员函数,如下所示:

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; }
Run Code Online (Sandbox Code Playgroud)

简单的测试程序(使用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, "!");
}
Run Code Online (Sandbox Code Playgroud)

这是一个实例.


nob*_*bar 5

执行一个worker类中的所有特化,并使用一个简单的函数作为隐式专用的包装器.

#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";
   }
Run Code Online (Sandbox Code Playgroud)

在这个例子中,特殊化unsigned char使它转换为一个,int以便cout将其显示为数字而不是字符,生成以下输出...

a=A, b=66
Run Code Online (Sandbox Code Playgroud)