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