如何在两个相同类型的模板上正确执行操作?

时间:2017-11-18 03:10:05

标签: c++ templates operator-overloading c++17

我从编译器收到以下错误:error: no match for 'operator+' (operand types are 'Expected<double>' and 'Expected<double>')预期是类型或异常。

template<typename T>
class Expected
{
    template<typename U>
    Expected<U> apply(std::function<U(T)> f)
    {
        if(!valid) return std::get<std::exception_ptr>(state);
        try
        {
            return f(std::get<T>(state));
        }
        catch(...)
        {
            return std::current_exception();
        }
    }
};   


#define MixedMode(op)\
template<typename T, typename U, typename V>\
Expected<U> op(Expected<T> t, Expected<V> v)\
{\
    return t.apply([&](T myT){return op(v,myT);});\
}\
template<typename T, typename U, typename V>\
Expected<U> op(Expected<T> t, V v)\
{\
    return t.apply([&](T myT){return op(myT,v);});\
}\
\
template<typename T, typename U, typename V>\
Expected<U> op(V v, Expected<T> t)\
{\
    return t.apply([&](T myT){return op(v,myT);});\
}\


MixedMode(operator+)

int main()
{
    Expected<double> a;
    Expected<double> b;

    a + b;
}

我相信我的头文件已经做得足够让他们重载并将它们加在一起。在第一个我期待两个模板加在一起。在我的主文件中,我只是打电话:

Expected<double> a;
Expected<double> b;
std::cout << a + b << std::endl;

然后抛出错误。在我添加Expected<U> op(Expected<T> t, Expected<V> v)\部分代码之前,我能够编译并运行,如果我有一个名为operator T() { return value(); }的函数,它会隐式地将Expected<T>转换为传入的任何类型。但是,我意识到我的apply函数从未被使用过。不仅如此,当我检查a+b的类型时,我返回了double而不是Expected<double>,因此我删除了operator T()函数,编译器通知我它没有&{ #39;知道如何将两个Expected<T>加在一起。

如何修复此错误?我整天都在反对这一切。

1 个答案:

答案 0 :(得分:0)

模板函数的主体从不用于推导模板参数。无法从参数中推断出U,因此会忽略您的+重载。

#define MixedMode(op)\
template<typename T, typename V>\
auto op(Expected<T> t, Expected<V> v)\
{\
  return t.apply([&](T myT){return op(v,myT);});\
}\
template<typename T, typename V>\
auto op(Expected<T> t, V v)\
{\
  return t.apply([&](T myT){return op(myT,v);});\
}\
template<typename T, typename V>\
auto op(V v, Expected<T> t)\
{\
  return t.apply([&](T myT){return op(v,myT);});\
}

这将无法编译,但这是因为您写错了apply

std::function不是lambda,lambda不是std::function。如果你推断std::function 999/1000次的类型你搞砸了,brcause std::function是关于类型擦除的,而演绎是关于类型演绎的,而那些是相反的概念

更重要的是,你正在向后组合它们,而且它们并不是那样构成的。

template<class F>
Expected<std::invoke_result_t<F&,T&>> apply(F f){

或类似的东西。