boost::static_visitor未能将多个不同的可能类型的函数模板专门化。

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

我想创建一个访问者函数,将我的那些值加在一起。boost::variant. 我使用模板来处理不同类型的情况,例如 int + float

typedef boost::variant<int, float> Values;

struct Add : public boost::static_visitor<Values> {
    template <typename T, typename U>
    auto operator() (T a, U b) const -> decltype(a + b) {
        return a + b;
    }
}

这个编译和工作正常

std::cout << boost::apply_visitor(Add{}, (Values)2, (Values)5) << std::endl;
std::cout << boost::apply_visitor(Add{}, (Values)2, (Values)5.123) << std::endl;

7

7.123

然而,我还想添加一个 std::string 进入 Values 变体,所以我也可以把字符串加在一起。我知道这是不可能的。string + int 例如,但我将确保这两个。Values 是一个字符串,然后再尝试通过访问者运行它们。

typedef boost::variant<int, float, std::string> Values;
std::cout << boost::apply_visitor(Add{}, (Values)"hello", (Values)"world") << std::endl;

然而,程序无法编译,给了我一个错误。

Failed to specialize function template 'unknown-type Add::operator()(T,U) const' 函数模板'未知型 Add::operator()(T,U) const'。

我知道 std::string 是一个对象而不是一个类型,因此这个错误有点道理,所以我试图通过重载 operatorAdd 当输入都是字符串的时候,就用这个结构。

auto operator() (std::string a, std::string b) const {
    return a + b;
}

但我得到的错误信息是

std::basic_string,std::allocator> Add::operator()(std::string,std::string) const': 不能将参数1从'T'转换为'std::string'

看起来它仍然试图通过模板化的访问者运行字符串参数。 我到底哪里做错了?有没有更好的方法可以完全实现我想做的事情?对不起,如果答案很明显的话,我对C++、boost和模板还是相当陌生。

c++ templates boost operator-overloading sfinae
1个回答
2
投票

apply_visitor 应该处理所有的组合(即使是无效的组合)。

你可以这样做。

using Values = boost::variant<int, float, std::string>;

// Helper for overload priority
struct low_priority {};
struct high_priority : low_priority{};

struct Add : public boost::static_visitor<Values> {

    template <typename T, typename U>
    auto operator() (high_priority, T a, U b) const -> decltype(Values(a + b)) {
        return a + b;
    }

    template <typename T, typename U>
    Values operator() (low_priority, T, U) const {
        // string + int, float + string, ...
        throw std::runtime_error("Incompatible arguments");
    }

    template <typename T, typename U>
    Values operator() (T a, U b) const {
        return (*this)(high_priority{}, a, b);
    }
};
© www.soinside.com 2019 - 2024. All rights reserved.