Overriding return type in function template specialization

前端 未结 4 1674
深忆病人
深忆病人 2020-12-04 07:49

I would like to specialize a function template such that the return type changes depending on the type of the template argument.

class ReturnTypeSpecializati         


        
相关标签:
4条回答
  • 2020-12-04 08:21

    You can do template specializations like so:

    template<typename T>
    T item() {
        return T();
    }
    
    template<>
    float item<float>() {
        return 1.0f;
    }
    
    0 讨论(0)
  • 2020-12-04 08:22

    Since the specialization has to agree with the base template on the return type, you can make it so by adding a "return type trait", a struct you can specialize and draw the true return type from:

    // 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.

    Note that you might want to stick to the following, so you only need to update the return-type in the item_return specialization.

    template<>
    item_return<float>::type foo<float>(){ ... }
    // note: No `typename` needed, because `float` is not a dependent type
    
    0 讨论(0)
  • 2020-12-04 08:35

    Perhaps you could use the following hack. Given these simple type traits:

    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; };
    

    You could write your class and specialized member function as follows:

    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; }
    

    Simple test program (uses C++11 just for verification):

    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, "!");
    }
    

    Here is a live example.

    0 讨论(0)
  • 2020-12-04 08:41

    Do all of the specialization in a worker class and use a simple function as a wrapper that will be specialized implicitly.

    #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";
       }
    

    In this example, the specialization of unsigned char causes it to be converted to an int so that cout will display it as a number instead of as a character, generating the following output...

    a=A, b=66
    
    0 讨论(0)
提交回复
热议问题