推导嵌套模板的模板参数失败

5

好的,我看了很多“无法推断模板参数”的问题,但似乎没有一个符合我的情况 - 或者我不理解答案...

有一个问题,我觉得它朝着正确的方向发展,但我没能从中提取出解决我的问题的方法。

我的头文件中精简后的代码如下:

template<typename T>
class TemplateProblem
{
public:
    // Do I really need this or did I miss something from the STL?
    template<typename Tin, typename Tout>
    struct UnaryFunction : public std::unary_function<Tin, Tout>
    {
        virtual Tout operator()(Tin input) = 0;
    };

    template<typename Tin, typename Tout>
    struct StaticCast : public UnaryFunction<Tin, Tout>
    {
        virtual Tout operator()(Tin input)
        {
            return static_cast<Tout>(input);
        }
    };

private:
    T * const _data;
    T const _bias;

    template<typename Tin>
    void Init(Tin * data, int length, UnaryFunction<Tin, T> mapper, Tin bias);

public:
    template<typename Tin>
    TemplateProblem(Tin * data, int length, Tin bias = Tin());

    template<typename Tin>
    TemplateProblem(Tin * data, int length, UnaryFunction<Tin, T> mapper, Tin bias = T());
};

template<typename T>
template<typename Tin>
void TemplateProblem<T>::Init(Tin * data, int length, UnaryFunction<Tin, T> mapper, Tin bias)
{
    T mappedBias = mapper(bias);
    for (int i = 0; i < length; i++)
    {
        _data[i] = data[i] + mappedBias;
    }
}

template<typename T>
template<typename Tin>
TemplateProblem<T>::TemplateProblem(Tin * data, int length, UnaryFunction<Tin, T> mapper, Tin bias = T())
    : _data(new T[length]), _bias(bias)
{
    Init(data, length, mapper, bias);
}

template<typename T>
template<typename Tin>
TemplateProblem<T>::TemplateProblem(Tin * data, int length, Tin bias = T())
    : _data(new T[length]), _bias(bias)
{
    StaticCast<Tin, T> cast;
    Init(data, length, cast, bias);
}

我是这样实例化它的:

unsigned char pixels[] = {23, 42, 65, 97};
TemplateProblem<int> tp(pixels, 4);

我从VS2012中得到了这些消息:

Error   1   error C2784: 'void TemplateProblem<T>::Init(Tin *,int,TemplateProblem<T>::UnaryFunction<Tin,T>,Tin)' : could not deduce template argument for 'TemplateProblem<T>::UnaryFunction<Tin,T>' from 'TemplateProblem<T>::StaticCast<Tin,Tout>'    ...\templateproblem.h   62  1   TemplateProblem
Error   2   error C2893: Failed to specialize function template 'void TemplateProblem<T>::Init(Tin *,int,TemplateProblem<T>::UnaryFunction<Tin,T>,Tin)' ...\templateproblem.h   62  1   TemplateProblem

根据这个答案的建议,如果我将这两个structclass中移出,同样会出现该错误。


1
实例化代码和错误消息完全无关。错误讲的是“StaticCast<Tin,Tout>”,但你在实例化代码中并没有用到它。 - Xeo
http://liveworkspace.org/code/4psoUf$0编译正常...您的代码(在更正之前)无法编译。 - ForEveR
@ForEveR:你提供的代码作为所有“UnaryFunction”的参考,而我的没有。这是否有所不同? - primfaktor
1
@primfaktor 这是有区别的,因为抽象类的对象不能被创建。UnaryFunction<Tin, T> mapper - 不合法。不管怎样,gcc编译正常。 - ForEveR
微软视觉工作室 2012 V 11.0.51106.01 更新 1 - primfaktor
显示剩余3条评论
1个回答

4
编译器错误对于指示实际问题并不是很有帮助。
实际问题在于你通过值将 `UnaryFunction` 传递给了你的 `Init` 函数(和其中一个构造函数),但所有的 `UnaryFunction<>` 实例化都会导致一个抽象类(它不能通过值传递)。 简单的解决方法是使用按引用传递 `UnaryFunction`,这样 `mapper` 就可以引用传递的真正对象。
STL 中传递仿函数的典型解决方案是使用一个单独的模板参数,像这样:
template<typename T>
template<typename Tin, Tmapper>
void TemplateProblem<T>::Init(Tin * data, int length, Tmapper mapper, Tin bias)
{
    T mappedBias = mapper(bias);
    for (int i = 0; i < length; i++)
    {
        _data[i] = data[i] + mappedBias;
    }
}

如果传入不兼容的 mapper,那么你就不需要使用 UnaryFunctionL<> 基类。当在函数体内使用它时会被诊断出来。

那个 Tmapper 模板参数起作用了,而且让生活更轻松。非常感谢! - primfaktor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接