Determine return type based on input parameter

2019-07-19 12:21发布

问题:

I'm trying to implement a generic configuration file parser and I'm wondering how to write a method in my class that is able to determine its return type, based on the type of an input parameter. Here's what I mean:

class Config
{
    ...
    template <typename T>
    T GetData (const std::string &key, const T &defaultValue) const;
    ...
}

In order to call the above method, I have to use something like this:

some_type data = Config::GetData<some_type>("some_key", defaultValue);

How can I get rid of the redundant specification? I saw that boost::property_tree::ptree::get() is able to do this trick, but the implementation is rather complicated and I wasn't able to decipher this complex declaration:

template<class Type, class Translator>
typename boost::enable_if<detail::is_translator<Translator>, Type>::type
get(const path_type &path, Translator tr) const;

If possible, I would like to do this, without creating a dependency on boost in the code that will use my Config class.

PS: I'm a n00b when it comes to C++ templates :(

回答1:

The enable_if in the code you’ve shown does something unrelated. In your case, you can just remove the explicit template specification, the compiler will infer it from the parameter:

some_type data = Config::GetData("some_key", defaultValue);

Even better, in C++11 you don’t even need to specify the variable type at declaration, it can be inferred as well:

auto data = Config::GetData("some_key", defaultValue);

… but note that C++ can only infer template arguments from parameters, not the return type. That is, the following does not work:

class Config {
    …
    template <typename T>
    static T GetData(const std::string &key) const;
    …
}
some_type data = Config::GetData("some_key");

Here, you’d either need to make the template argument explicit, or use a trick that returns a proxy class rather than the actual object, and defines an implicit conversion operator. Messy and most of the time unnecessary.