在C ++中将模板变量传递给模板函数14

时间:2015-05-09 17:54:28

标签: c++ templates compiler-construction lazy-evaluation c++14

我正在编写一个编译成C ++的编译器,并且我的C ++代码存在类型问题。该语言是懒惰的,所以我们有一个惰性值包装器,Chunk。以下是其中的一部分,以及有问题的代码:

#include <functional>
#include <memory>

template<class T>
class Chunk
{
public:
    Chunk();
    Chunk(std::function<T()> f);
    T operator()();

    std::function<T()> f_;

private:
    std::shared_ptr<T> cache_;
};

template<class T>
T Chunk<T>::operator()()
{
    if(cache_ == nullptr)
        cache_ = std::make_shared<T>(f_());
    return *cache_;
}

template<class T, class F>
T operator*(Chunk<T> t1, Chunk<F> t2)
{
    return t1() * t2();
}

template<class T, class... Args>
T apply(Chunk<std::function<T(Args...)>> c, Args... as)
{
    return c()(as...);
}

template<class F>
auto toChunk(F f) -> Chunk<decltype(f())>
{
    return Chunk<decltype(f())>(f);
}

template<class T, class F>
struct ops
{
    static const auto multiply =
        toChunk([]() { return ops::multiply_; });

    static const auto multiply_(Chunk<T> x, Chunk<F> y) -> decltype(x * y)
    {
        return x * y;
    }
};

int main()
{
    Chunk<double> t = toChunk([]() { return 1.0; });
    Chunk<float> f = toChunk([]() { return 2.0f; });

    apply(ops::multiply, t, f);
    return 0;
}

我无法找出multiply的定义,以便在没有used without template parameters错误的情况下完成此工作。 (这里可能存在第二个问题,因为multiply_不是std::function,但编译器首先会缺少模板参数。)

我可以为每对类型编写很多重载,但这真的很难看。我尝试在没有模板类的情况下将模板变量相乘,即使我使用的是C ++ 14,但使用此替代定义在cannot resolve address of overloaded function得到multiply_

template<class T, class F>
auto multiply_(Chunk<T> x, Chunk<F> y) -> decltype(x * y)
{
    return x * y;
}
template<class T, class F>
Chunk<decltype(multiply_)> multiply = toChunk([]() { return multiply_; });

我当然将ops::multiply更改为multiply。有什么建议可以克服这个问题吗?

2 个答案:

答案 0 :(得分:2)

ops是类模板的名称。要在其定义之外引用类模板的成员,您需要指定模板参数。

如果您修复此错误,则会有更多错误。

答案 1 :(得分:0)

我最终使用了完全不同的解决方案。我通过添加第二个定义来重载apply

template<class F, class... Args>
auto apply(F f, Args... as) -> decltype(f(as...))
{
    return f(as...);
}

简单地重写:

auto multiply = [](auto x, auto y) { return x * y; };

所以我们的库函数不会在延迟包装器中,而用户定义的函数(不能是我们语言中的模板)会。