gpt4 book ai didi

c++ - 在std::variant中保存的类型上调用<<运算符?

转载 作者:行者123 更新时间:2023-12-02 09:49:36 25 4
gpt4 key购买 nike

我有一个这样的结构:

// Literal.hpp
struct Literal
{
std::variant<
std::nullptr_t,
std::string,
double,
bool
>
value;

friend std::ostream &operator<<(std::ostream &os, Literal &literal);
};

我试图像这样实现<<操作符:
// Literal.cpp
Literal::Literal() : value(value) {}

std::ostream &operator<<(std::ostream &os, const Literal &literal)
{
std::visit(/* I don't know what to put here!*/, literal.value);
}

我已经尝试过像这样实现运算符(请注意:我会采用任何优雅的解决方案,它不一定是下面的此实现的解决方案)
// In Literal.cpp
std::ostream &operator<<(std::ostream &out, const Literal literal)
{
std::visit(ToString(), literal.value);
return out;
}

struct ToString; // this declaration is in literal.hpp

void ToString::operator()(const std::nullptr_t &literalValue){std::cout << "null";}
void ToString::operator()(const char &literalValue){std::cout << std::string(literalValue);}
void ToString::operator()(const std::string &literalValue){std::cout << literalValue;}
void ToString::operator()(const double &literalValue){std::cout << literalValue;}
void ToString::operator()(const bool &literalValue){std::cout << literalValue;}

但是在我的主要函数中,传递char数组文字并不会在运行时将其转换为 bool(boolean) 值!忽略运算符重载,取一个char:
main() {
Literal myLiteral;
myLiteral.value = "Hello World";
std::cout << myLiteral << std::endl;
}

最佳答案

这是标准库中的错误。大概您正在使用libstc++(GNU C++标准库),因为这是Godbolt所显示的困惑。如果使用libc++(Clang / LLVM的C++标准库)进行编译,则可以按预期工作。根据 std::vector<Types...>::operator=(T&& t) 's cppreference page,它

Determines the alternative type T_j that would be selected by overload resolution for the expression F(std::forward<T>(t)) if there was an overload of imaginary function F(T_i) for every T_i from Types... in scope at the same time, except that:

  • An overload F(T_i) is only considered if the declaration T_i x[] = { std::forward<T>(t) }; is valid for some invented variable x;

  • If T_i is (possibly cv-qualified) bool, F(T_i) is only considered if std:remove_cvref_t<T> is also bool.



在这种情况下,最后一条是存在的。因为很多东西都可以转换为 bool,但是我们通常不打算进行此转换,所以该子句会导致通常不会选择的转换序列被选中( char const*bool是标准转换,但是 std::string是“用户定义的”,通常被认为是“更差”)。您的代码应将 value设置为其 std::string替代,但是您的库的 std::variant实现已损坏。可能已经打开了一张问题单,但是如果没有,则是打开一张问题单的理由。如果您对库感到困惑,那么将文字显式标记为 std::string应该可以:
literal.value = std::string("Hello World");

对于优雅的问题,请使用缩写模板lambda。
std::ostream &operator<<(std::ostream &os, Literal const &literal)
{
std::visit([](auto v) { std::cout << v; }, literal.value);
// or
std::visit([](auto const &v) {
// gets template param vvvvvvvvvvvvvvvvvvvvvvvvv w/o being able to name it
if constexpr(std::is_same_v<std::decay_t<decltype(v)>, std::nullptr_t>) {
std::cout << "null";
} else std::cout << v;
}, literal.value);
// only difference is nullptr_t => "nullptr" vs "null"

return std::cout;
}

另外,您的 friend声明与定义不匹配。实际上,无论如何都不应使用 friend编码,因为它不需要访问 private成员。
// declaration in header, outside of any class, as a free function
std::ostream &operator<<(std::ostream&, Literal const&);
// was missing const ^^^^^

关于c++ - 在std::variant中保存的类型上调用<<运算符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61298696/

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