c++ - 尽管使用 std::is_same 测试它是一个 std::string,但无法将类型名从 int 转换为 std::string

标签 c++

这是我第一次使用模板,所以我怀疑我使用不当。

在我的代码中,我多次从控制台获得每行以空格分隔的值列表。有时我希望列表是一对 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::stringint 并且我输入:

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
}

这会产生以下错误,但 ba 不会引发任何错误:

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/

相关文章:

python - Boost.Python 因静态库而失败

c++ - 在 g++ 编译器中使用 strlen 获取数组的长度

c++ - LoadLibrary A 在哪里寻找文件?

c++ - 在 C++ 中使用(丑陋的)C 代码与 extern "C"

C++多维结构数组

使用函数的 C++ 字符串输入

c++ - 如何在 C++ 中将与谓词匹配的元素从一个 vector 传输到另一个 vector ?

c++ - 使用 std::async 引用对象

c++ - 为什么 memory_order_relaxed 在 x86 上使用原子(锁前缀)指令?

c++ - 多线程C++ dll全局变量导致崩溃