hczstev
hczstev

Reputation: 73

c++ templately template specialization

I have a template function, which has no argument

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

I want to specialize it for some templated class like vector like

template<typename T>
template<>
vector<T> cast<vector<T>>() {
    // something special
    return vector<T>()
}

since it takes no argument, so it cannot be overloaded. What should I do to implement it?

Upvotes: 0

Views: 88

Answers (1)

Jarod42
Jarod42

Reputation: 217970

Functions cannot be partial specialized.

You might

  • provide another customization point

    • class which can be partial specialized:

      template <typename T>
      struct impl
      {
          T operator()() const { return T(); }
      };
      
      template <typename T>
      struct impl<std::vector<T>>
      {
          std::vector<T> operator()() const { /*Something special*/ return std::vector<T>(); }
      };
      
      template<typename T>
      T cast() {
          return impl<T>{}();
      }    
      
    • forward to overload functions with "tag":

      template <typename T>
      T impl(std::struct_identity<T>)
      {
          return T();
      };
      
      template <typename T>
      std::vector<T> impl(std::struct_identity<std::vector<T>>)
      {
          /*Something special*/
          return std::vector<T>();
      };
      
      template<typename T>
      T cast() {
          return impl(std::struct_identity<T>{});
      }    
      
  • Create the different (exclusive) overloads (from the start):

    // traits to detect std::vector
    template <typename T>
    struct is_vector : std::false_type {};
    
    template <typename T, typename A>
    struct is_vector<std::vector<T, A>> : std::true_type {};
    
    template<typename T, std::enale_if_t<!is_vector<T>::value, int> = 0>
    T cast() {
        return T();
    }
    
    template<typename T, std::enale_if_t<is_vector<T>::value, int> = 0>
    T cast() {
        /*Something special*/
        return T();
    }
    
  • or since C++17, use if constexpr:

    // traits to detect std::vector
    template <typename T>
    struct is_vector : std::false_type {};
    
    template <typename T, typename A>
    struct is_vector<std::vector<T, A>> : std::true_type {};
    
    template<typename T>
    T cast() {
        if constexpr(is_vector<T>::value) {
            /*Something special*/
            return T();
        } else {
            return T();
        }
    }
    
  • or since C++20, you might overload with constraint:

    // traits to detect std::vector
    template <typename T>
    struct is_vector : std::false_type {};
    
    template <typename T, typename A>
    struct is_vector<std::vector<T, A>> : std::true_type {};
    
    template<typename T>
    T cast() {
        return T();
    }
    
    template<typename T>
    requires(is_vector<T>)
    T cast() {
        /*Something special*/
        return T();
    }
    

Upvotes: 2

Related Questions