gpt4 book ai didi

c++ - 缺少用户定义的to_string()的编译时检测

转载 作者:行者123 更新时间:2023-12-01 14:52:37 26 4
gpt4 key购买 nike

我想为我创建的每种对象类型提供to_string(obj)函数。
我找到了this question,应用了accepted answer,并且可以正常工作。到现在为止还挺好。

然后,我创建了一个新类型,但忘了为此写一个to_string()(或者更好:我无意中使ADL无法访问它)。问题是:我的程序仍然编译良好,并且在运行时我得到了晦涩的堆栈溢出(TM)。

有办法获取合理的错误消息吗?

这是一个演示该问题的小程序:notstd::to_string()notstd::adl_helper::as_string()之间的无限递归。

#include <iostream>
#include <string>

namespace notstd {
namespace adl_helper {
using std::to_string;

template<class T>
std::string as_string( T&& t ) {
return to_string( std::forward<T>(t) );
}
}
template<class T>
std::string to_string( T&& t ) {
std::cout << "called" << std::endl; // <-- this is to show what's going on
return adl_helper::as_string(std::forward<T>(t));
}

class A {
/* both versions are needed, or the perfect forwarding candidate will
* always be chosen by the compiler in case of a non-perfect match */
//friend std::string to_string(A &a) { return std::string("a"); }
//friend std::string to_string(const A &a) { return std::string("a"); }
};
}


int main(int argc, char** argv) {

notstd::A a;

std::cout << to_string(a) << std::endl;
}

我尝试创建一个接受另一个参数的包装器函数,以用于执行抗递归检查,如下所示:
#include <iostream>
#include <string>
#include <cassert>

namespace notstd {
namespace wrap_std {
std::string to_string(double v, bool) { return std::to_string(v); }
/* .... etc..... */
}

namespace adl_helper {
using wrap_std::to_string;

template<class T>
std::string as_string( T&& t ) {
return to_string( std::forward<T>(t), true );
}
}
template<class T>
std::string to_string( T&& t, bool recurring = false ) {
std::cout << "called" << std::endl;
assert(!recurring);
return adl_helper::as_string(std::forward<T>(t));
}

class A {
/* both versions are needed, or the perfect forwarding candidate will
* always be chosen by the compiler in case of a non-perfect match */
//friend std::string to_string(A &a) { return std::string("A"); }
//friend std::string to_string(const A &a) { return std::string("A"); }
};
}


int main(int argc, char** argv) {

notstd::A a;

std::cout << to_string(a) << std::endl;
}

这里的问题是:
  • 我必须包装所有 std::to_string()重载
  • 我只会遇到运行时错误,但我认为可以并且应该在广告编译时检测到该问题
  • 我可能会增加一些开销,仅在开发过程中才有用:也许我可以添加一些宏以在 Release模式下停用所有这些功能,但是它将添加更多的工作

  • 也许我可以使用模板来包装 std::to_string()并为我的类型创建专门化...这将是一个完全不同的野兽,但是如果没有合适的专门化,至少它将提供编译时错误。我将不得不再次包装所有 std::to_string()重载,并且我可能不得不(几乎)忘记ADL,至少要等到所有编译器都支持c++ 20为止(如果我理解得很好)。

    有谁有更好的解决方案?

    谢谢!

    最佳答案

    接受的answer的想法是不同的:您将A 放在 notstd命名空间之外,然后使用合格的notstd::to_string而不是不合格的to_string。那是:

    namespace notstd {
    // ...
    }

    class A {
    friend std::string to_string(const A&);
    };

    A a;
    std::cout << notstd::to_string(a);

    现在,如果没有 friend函数,您的代码将无法编译。而且,您只需要一个 friend 函数(使用 const A&),因为 notstd::to_string(T&&)不会在 adl_helper::as_string(T&&)内部的重载集中出现。

    A放入 notstd会破坏一切。您有无限递归问题,并且在存在 A候选者的情况下需要两个 friend 来处理 const Anotstd::to_string(T&&)情况:如果仅定义一个 friend ,则在一种情况下该候选者是更好的匹配项,因为应该添加/删除 const限定词调用好友功能。

    关于c++ - 缺少用户定义的to_string()的编译时检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62139127/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com