boost :: static_visitor无法使用多种可能的类型来专门化功能模板

时间:2020-04-29 12:10:39

标签: c++ templates boost operator-overloading sfinae

我正在尝试创建一个访问者函数,该函数会将我的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;

但是该程序无法编译,给了我错误:

未能专门化功能模板'unknown-type Add :: operator()(T,U)const'

我知道std::string是一个对象而不是类型,因此这种错误类型是有道理的,因此,我试图通过在{{1}中重载operator来产生一种特殊情况}当两个输入都是字符串时的结构:

Add

但是我得到了错误

std :: basic_string,std :: allocator>添加:: operator()(std :: string,std :: string)const':无法将参数1从'T'转换为'std :: string'

看起来它仍在尝试通过模板化访问者运行string参数。我要去哪里错了?有没有更好的方法可以完全实现我要完成的任务?抱歉,如果答案很明显,我还是C ++,boost和模板的新手。

1 个答案:

答案 0 :(得分: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);
    }
};