代码之家  ›  专栏  ›  技术社区  ›  Denis Steinman

如果模板类型也可以是字符串,如何将其转换为字符串?

  •  4
  • Denis Steinman  · 技术社区  · 6 年前

    我有课:

    template <typename val_t>
    class tracer_t : public base_tracer_t<val_t> {
        std::vector<std::string> m_trace;
    public:
        virtual void push_fact(val_t fact) override {
            std::string str = "+ fact: " + to_string(fact);
            m_trace.push_back(std::move(str));
        }
    
        virtual void push_rule(const std::string &id, val_t val, bool tg) override {
            std::string str = "+ ";
            if (tg) { str += "target: "; }
            else { str += "rule: "; }
            str += id + " -> " + to_string(val);
            m_trace.push_back(std::move(str));
        }
    
        virtual void print() override {
            std::cout << "Stack trace: " << std::endl;
            for (auto it = m_trace.begin(); it != m_trace.end(); ++it) {
                std::cout << (*it) << std::endl;
            }
        }
    private:
        std::string to_string(val_t val) {
            if (std::is_same<val_t, std::string>::value) {
                return (std::string)val;
            }
            return std::to_string(val);
        }
    };
    

    问题是如果 val_t std::string 因为:

    tracer.hpp:49: error: no matching function for call to ‘to_string(std::__cxx11::basic_string<char>&)’
             return std::to_string(val);
                    ~~~~~~~~~~~~~~^~~~~
    

    但我不知道怎么解决。我试图手动检查类型,但错误在编译时,所以没有帮助

    2 回复  |  直到 6 年前
        1
  •  5
  •   francesco    6 年前

    你只需要为 to_string

    std::string to_string(const std::string& s) { return s; }
    

    您可以将上面的代码作为私有方法放在类中,或者放在适当的命名空间中,这样可以避免在某人使用您的代码并希望编写自己的重载 托弦 .

    编辑:正如下面的注释所指出的,您不能在 std 命名空间,作为 std::to_string 是禁止的,见 Extending the namespace std .

    编辑:如果你需要打电话 STD:toxx字符串 ,您可能需要添加一个 托弦 模板函数到您的代码为

    template <typename T>
    typename std::enable_if<!std::is_convertible<T, std::string>::value, std::string>::type to_string(T r) const { return std::to_string(r); }
    

    (别忘了 #include <type_traits> 为此)。

    这是因为,即使导入标准库 STD:toxx字符串 通过 using namespace std ,成员函数 托弦 将优先考虑。参见讨论: C++: Why member function has priority over global function . Here 您可以看到一个最小的例子。

        2
  •  6
  •   Petok Lorand    6 年前

    如果您不想专门化整个类 std::string 你可以使用 std::enable_if if constexpr (C++ 17)

    auto to_string(val_t val)
        -> typename std::enable_if<std::is_same<val_t, std::string>::value, std::string>::type 
    {
        return static_cast<std::string>(val);
    }
    
    auto to_string(val_t val)
        -> typename std::enable_if<!std::is_same<val_t, std::string>::value, std::string>::type 
    {
        return std::to_string(val);
    }
    

    或者更现代的方法, 如果康斯特雷普

    auto to_string(val_t val)
    {
        if constexpr (std::is_same<val_t, std::string>::value)
        {
            return static_cast<std::string>(val);
        }
        else
        {
            return std::to_string(val);
        }
    }