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.
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.
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.
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.
Explicit (full) specializationAllows customizing the template code for a given set of template arguments.
Don't specialize function template.
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.
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? }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With