在当前状态下,程序验证数据类型的输入:int和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;
}
通过每种数据类型的两个函数获得输入:get_int()和get_word()。
对于未指定int范围且名称可能包含任何字符的情况,验证函数是可选参数。
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;
}
我想知道,如果可能的话,如何正确地声明一个功能模板,可以在需要验证时简化流程。
template<typename T> bool get_item(const string&, T&, ???);
使用不同的验证函数重载函数模板get_item是一个潜在的解决方案吗?
答案 0 :(得分:4)
如果你真的喜欢函数指针,那么
template<typename T> bool get_item(const string&, T&, bool (*)(const T&) = nullptr);
或
template<typename T> bool get_item(const string&, T&, bool (*)(T) = nullptr);
匹配valid*
函数的现有签名(请注意,这会产生副本)。
你也可以使它完全通用:
template<typename T, typename F> bool get_item(const string&, T&, F);
要处理不需要验证的情况,可以使用单独的重载:
template<typename T> bool get_item(const string &s, T &t){
return get_item(s, t, [](const T&){return true;});
}
答案 1 :(得分:0)
将验证器作为模板类型:
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);
这里有一个隐含的模板策略,Validator可以用T调用并返回一个bool。由于它还没有在C ++中的概念,你可能只是评论模板策略。