How can I specialize a template member function for std::vector

前端 未结 2 670
情话喂你
情话喂你 2020-12-15 17:26

I need to define a get method in two different ways. One for simple types T. And once for std::vector.

template
const T& Parameters::ge         


        
相关标签:
2条回答
  • 2020-12-15 18:25

    Don't specialize function template.

    • Why Not Specialize Function Templates?
    • Template Specialization and Overloading

    Instead, use overload.

    Write a function template get_impl to handle the general case, and overload (not specialize) this to handle the specific case, then call get_impl from get as:

    template<typename T>
    const T& Parameters::get(const std::string& key)
    {
         //read the explanation at the bottom for the second argument!
         return get_impl(key, static_cast<T*>(0) );
    }
    

    And here goes the actual implementations.

    //general case
    template<typename T>
    const T& Parameters::get_impl(const std::string& key, T*)
    {
        Map::iterator i = params_.find(key);
        return boost::lexical_cast<T>(boost::get<std::string>(i->second));
    }
    
    //this is overload - not specialization
    template<typename T>
    const std::vector<T>& Parameters::get_impl(const std::string& key, std::vector<T> *)
    {
          //vector specific code
    }
    

    The static_cast<T*>(0) in get is just a tricky way to disambiguate the call. The type of static_cast<T*>(0) is T*, and passing it as second argument to get_impl will help compiler to choose the correct version of get_impl. If T is not std::vector, the first version will be chosen, otherwise the second version will be chosen.

    0 讨论(0)
  • 2020-12-15 18:29

    Erm. call it something else? e.g.

    template<typename T>
    const T& Parameters::getVector(const std::string& key)
    {
      Map::iterator i = params_.find(key);
      std::vector<std::string> temp = boost::get<std::vector<std::string> >(i->second)
      // T is already a vector
      T ret; ret.reserve(temp.size());
      for(int i=0; i<temp.size(); i++){
         ret.push_back(boost::lexical_cast<typename T::value_type>(temp[i]));
      }
      return ret;  
    }
    

    You'll have to call this as:

    foo.getVector<std::vector<int> > ("some_key");
    

    Nothing in your question precludes this.

    Now, if you really do need to use get(), then you have to rely on partially specializing a structure, as function partial specialization is not supported by the language.

    This is a lot more complicated, for example:

    template <typename T>
    struct getter
    {
      const T& operator()(std::string const& key)
      {
        // default operations
      }
    };
    
    // Should double check this syntax 
    template <typename T>
    struct getter<std::vector<T, std::allocator<T> > >
    {
      typedef std::vector<T, std::allocator<T> > VecT;
      const VecT& operator()(std::string const& key)
      {
        // operations for vector
      }
    };
    

    Then in you method becomes:

    template<typename T>
    const T& Parameters::get(const std::string& key)
    {
      return getter<T>()(key); // pass the structures getter needs?
    }
    
    0 讨论(0)
提交回复
热议问题