0
votes

In its current state the program validates input for data types: int and string.

//valid score range between 0 and 100
bool validScore(int value) 
{
  if(value < 0 || value > 100)
      return false;
  return true;
}
//valid name composed of letters
bool validName(string word)
{
  for(int i = 0; i < word.length(); i++)
  {
    if(!isalpha(word[i]) )
        return false;
  }
  return true;
}

Input is obtained through two functions for each data type: get_int() and get_word().

The validation functions are optional parameters for cases where int range is unspecified and names may contain any character.

bool get_int(const string&, int&, bool(*validScore)(int) = 0);
bool get_word(const string&, string&, bool(*validWord)(const string) = 0);

// bool get_int(const string& prompt, int&n, (*validScore)(int)) 
bool get_word(const string& prompt, string&word, bool(*validWord)(const string) )
{
  while(1)
  {
    string line;
    cout << prompt;

    if(!getline(cin, line) 
      break;

    istringstream iss(line);

    if(iss >> word) // iss >> n
    {
      // validScore == 0 || validScore(n)
      if(validWord == 0 || validWord(word)) 
        return true;
    }
  }
  return false;
}

I am wondering, if possible, how to correctly declare a function template that could streamline the process when validation is required.

template<typename T> bool get_item(const string&, T&, ???);

Would overloading the function template get_item with the different validation functions be a potential solution?

2
seems like you just want a template function valid(const T &), that only has specializations for types it supports?dwcanillas

2 Answers

4
votes

If you really like function pointers, then

template<typename T> bool get_item(const string&, T&, bool (*)(const T&) = nullptr);

or

template<typename T> bool get_item(const string&, T&, bool (*)(T) = nullptr);

to match the existing signatures of your valid* functions (note that this would incur a copy).

You can also make it completely generic:

template<typename T, typename F> bool get_item(const string&, T&, F);

To handle the case where no validation is required, a separate overload can be used:

template<typename T> bool get_item(const string &s, T &t){
    return get_item(s, t, [](const T&){return true;});
}
0
votes

Take the validator as a template type:

template<class T>
bool get_item(const string& prompt, T& item);

template<class T, class Validator>
bool get_item(const string& prompt, T& item, Validator validator);

There is an implied template policy here that a Validator is callable with a T and returns a bool. Since concepts it not yet in C++, you might just comment the template policy.