在std :: variant中的类型上调用<

问题描述 投票:0回答:1

我有这样的结构:

// 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数组文字并不会在运行时将其转换为布尔值!忽略运算符重载,取一个字符:

main() {
    Literal myLiteral;
    myLiteral.value = "Hello World";
    std::cout << myLiteral << std::endl;
}
c++ variant visitor
1个回答
0
投票

const char*不是value可以容纳的类型。将"Hello World"分配给myLiteral.value时,有两个可能的转换链:

  • const char*-> bool
  • const char*-> std::string

前者是内置转换,而后者是用户定义的转换。因此,认为转换为bool更好。

要解决此问题,您可以使用包装器功能,而不是直接设置value

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

    template <typename T>
    void setValue(T val)
    {
        value = val;
    }

    void setValue(const char* val)
    {
        setValue(std::string{val});
    }
};

Live Demo

这利用了以下事实:重载解析将功能模板实例化视为比非模板函数更差的匹配,因此myLiteral.setValue("Hello World")将调用Literal::setValue(const char*)而不是Litaral::setValue<const char*>(const char*)

© www.soinside.com 2019 - 2024. All rights reserved.