Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
348 views
in Technique[技术] by (71.8m points)

c++ - Template type deduction in parameter and return type

in our current code base we have code that looks something like the below (this is of course a simplified version):

#include <map>
#include <string>
#include <iostream>

using namespace std;

// General template function to convert an enum to a string, given a converter-container
// The converter-container is either a map, or a vector/array etc. of pair, 
// e.g. something that has enum in .first and string in .second

template<typename Container, typename Index>
string toString(Container&& names, Index&& index, const string& noMatch = "NoMatch")
{
    for (auto&& elem : names) {
      if (elem.first == index) {
         return elem.second;
      }
   }
   return noMatch;
}


// Simple example enum
enum class Color
{
    red, green, blue, pink
};

// Example of two converter-container types
constexpr array colors1 = {pair{Color::red, "Red"}, pair{Color::green, "Green"}, pair{Color::blue, "Blue"}};
const map<Color, string> colors2  =  {{Color::red, "Red"}, {Color::green, "Green"}, {Color::blue, "Blue"}};


int main()
{
    cout << toString(colors1, Color::red) << " " << toString(colors2, Color::blue) << " "
     << toString(colors2, Color::pink) << endl;     
}

This code works as expected, and prints out "Red Blue NoMatch"

However, I'd like to rewrite the toString function so that it does not return string, but whatever type that is stored in the convert-container (e.g. string, string_view or char*).

If not for the noMatch part, the task would be simple, just to have "auto" instead of "string" as return type:

template<typename Container, typename Index>
auto toString(Container&& names, Index&& index)
{
    for (auto&& elem : names) {
      if (elem.first == index) {
         return elem.second;
      }
   }
   return begin(names)->second;
}

This works and prints out "Red Blue Red", but is not the solution I am looking for. What I look for is a way to have:

template<typename Container, typename Index>
auto toString(Container&& names, Index&& index, const <returnType>& noMatch = "")
{
    for (auto&& elem : names) {
      if (elem.first == index) {
         return elem.second;
      }
   }
   return noMatch;
}

But as you see, I need to fill in something for <returnType>, and I have no Idea what it would be. I can split the function into two different, one for maps and one for array/vector of pairs if that would help, but I would like to be able to keep the same calling syntax.

FWIW, we are currently using gcc 9.2 with c++17 enabled.

Thanks.

question from:https://stackoverflow.com/questions/65900901/template-type-deduction-in-parameter-and-return-type

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Just deduce the type of second, something like:

template<typename Container, typename Index,
         typename NoMatchType=decltype(std::declval<typename Container::value_type &&>().second)>
auto toString(Container&& names, Index&& index,
              const NoMatchType &noMatch=NoMatchType{})

(You can also use NoMatchType instead of auto here, if you wish)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...