简体   繁体   中英

C++ function switch on value

I have a templated function

template <typename S, typename T>
string DoStuff(const S& s, const T& t, const string& format) {
    ...
}

But format changes the function's behaviour completely (imagine values like "csv", "json", etc.). So it would make a bit more sense to have separate functions.

I feel like I'm missing something obvious, that this should be possible with some sort of specialisation. Otherwise, I just have to add a dispatch function, which would work but feels like I've missed something obvious.

template <typename S, typename T>
string DoStuff(const S& s, const T& t, const string& format) {
    if (format == "csv")
        return DoStuffCSV(s, t);
    if (format == "json")
        return DoStuffJSON(s, t);
    // ...
}

template <typename S, typename T>
string DoStuffCSV(const S& s, const T& t) {
...
}

template <typename S, typename T>
string DoStuffJSON(const S& s, const T& t) {
...
}

Conceptually, I want this (which of course doesn't work)

template <typename S, typename T, string("csv")>
string DoStuff(const S& s, const T& t) {
...
}

template <typename S, typename T, string("json")>
string DoStuff(const S& s, const T& t) {
...
}

So long as you want to depend on a value that can only be determined at run time, you're not missing anything: compile-time specialization is simply impossible.

However, as suggested by commenters, you can specialize according to a value that's known at compile-time, like an enum.

As @bolov and @Nathan Oliver write, you can do this with an enum.

To branch at compile time, I'd add std::integral_constant :

#include <type_traits>                                                                                                                                                                                   

enum class type
{   
    txt = 1,
    cst = 2,
};  

using txt_specifier = std::integral_constant<type, type::txt>;
using csv_specifier = std::integral_constant<type, type::csv>;

The latter two are types , and you can overload on them at compile time (and using the numeric values, do fancy metaprogramming things if needed further).

If you want to select the correct code with a run-time value, you probably need some sort of despatch table:

const auto dispatch = []{
    std::map<std::string,std::function<string(const S&,const T&)>> table;
    table("csv") = [](const S& s,const T& t) { return do_stuff_csv(s,t); };
    table("json") = [](const S& s,const T& t) { return do_stuff_json(s,t); };
    return table;
}();

It's an exercise for the reader to generalise this sufficiently, and to take care of validating the format parameter...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM