Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

templates

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

template<typename T> const T& Parameters::get(const std::string& key) {     Map::iterator i = params_.find(key);     ...     return boost::lexical_cast<T>(boost::get<std::string>(i->second));     ... } 

How can I specialize this method for std::vector. As there the code should look something like this:

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

But I do not know how to specialize the function for this. Thanks a lot.

like image 900
tune2fs Avatar asked Nov 29 '11 17:11

tune2fs


People also ask

How do you define a template member function?

You may define a template member function outside of its class template definition. When you call a member function of a class template specialization, the compiler will use the template arguments that you used to generate the class template.

When we specialize a function template it is called?

To do so, we can use a function template specialization (sometimes called a full or explicit function template specialization) to create a specialized version of the print() function for type double.

How do you define a template function in C++?

Defining a Function TemplateA function template starts with the keyword template followed by template parameter(s) inside <> which is followed by the function definition. In the above code, T is a template argument that accepts different data types ( int , float , etc.), and typename is a keyword.

What is explicit template specialization?

Explicit (full) specializationAllows customizing the template code for a given set of template arguments.


2 Answers

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.

like image 193
Nawaz Avatar answered Oct 19 '22 23:10

Nawaz


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? } 
like image 24
Nim Avatar answered Oct 19 '22 22:10

Nim