这是我第一次使用模板,所以我怀疑我使用不当。
在我的代码中,我多次从控制台获得每行以空格分隔的值列表。有时我希望列表是一对 std::strings
或一个 std::string
和一个 int
- 你明白了。所以我想创建一个类型不明确的函数,它可以通过引用列表一次处理所有问题。
以下工作正常:
template<typename A, typename B> void getInputList(std::vector<std::pair<A, B>> &list) {
//redacted while loop
A a;
B b;
if ((ss >> a >> b) && ss.eof())
list.push_back(std::make_pair(a, b));
else {
std::cout << "Bad values ignored" << ((list.size() != 0) ? ", previous values still in buffer.\n" : ".\n");
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
但是,如果类型是 std::string
和 int
并且我输入:
56 56
代码会接受它,我希望字符串完全是 alpha。因此,我添加了一个测试来查看是否有一个输入是 std::string
,如果是,请确保它没有数字:
template<typename A, typename B> void getInputList(std::vector<std::pair<A, B>> &list) {
//redacted while loop
A a;
B b;
if ((ss >> a >> b) && ss.eof()) {
if (std::is_same<A, std::string>::value)
if(std::all_of(a.begin(), a.end(), ::isdigit))
continue;
if (std::is_same<B, std::string>::value)
if(std::all_of(b.begin(), b.end(), ::isdigit))
continue;
list.push_back(std::make_pair(a, b));
continue;
}
//more redacted code
}
这会产生以下错误,但仅 b
,a
不会引发任何错误:
left of '.begin' must have class/struct/union
left of '.end' must have class/struct/union
我创建了一个临时函数来查看原因,而 a
的类型为 A
,而 b
的类型为 int
。
bool isString(std::string in) {
return std::all_of(in.begin(), in.end(), ::isdigit);
}
template<typename A, typename B> void getInputList(std::vector<std::pair<A, B>> &list) {
//redacted while loop
A a;
B b;
if ((ss >> a >> b) && ss.eof()) {
if (std::is_same<A, std::string>::value)
if(isString(a))
continue;
if (std::is_same<B, std::string>::value)
if(isString(b))
continue;
list.push_back(std::make_pair(a, b));
continue;
}
//more redacted code
}
给出:
cannot convert from 'int' to 'std::string'
如果我将 std::to_string
应用于两者,则 a
会产生错误:
'std::to_string': none of the 9 overloads could convert all the argument types
因为它是 A
类型,所以它应该是...
我做错了什么?
最佳答案
在大多数情况下,函数模板特化中的所有语句都必须有效,即使它们永远不会被执行。
如果你可以使用 C++17,它引入了“if constexpr
”来解决这个问题:当你键入 if constexpr
而不是仅仅 if
,必须可以在编译时评估条件,并且对于给定的一组模板参数不可能执行的任何受控语句根本不会用这些模板参数实例化。
如果您不能使用 C++17,您可以分派(dispatch)一个辅助函数来进行验证。关键是根据类型是 std::string
还是其他类型调用不同的函数。
// A string must not be all digits:
inline bool validateInput(const std::string& s) {
return !std::all_of(s.begin(), s.end(), ::isdigit);
}
// Any other type is always valid:
template <typename T>
bool validateInput(const T&) { return true; }
template<typename A, typename B>
void getInputList(std::vector<std::pair<A, B>> &list) {
// ...
while (something()) {
A a;
B b;
if ((ss >> a >> b) && ss.eof()) {
if (!validateInput(a)) continue;
if (!validateInput(b)) continue;
list.push_back(std::make_pair(a, b));
continue;
}
// ...
}
}
关于c++ - 尽管使用 std::is_same 测试它是一个 std::string,但无法将类型名从 int 转换为 std::string,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46880328/