c ++嵌套模板参数查找失败

时间:2013-08-08 11:40:48

标签: c++ templates c++11

考虑:

#include <vector>
template<int N> class B {};
template<int N> class A {};

template<int N, template<int> class T>
void doSomething(T<N> const& my_type) {
    //do sth...
}



int main() {
    B<42> b;
    doSomething(b); //OK

    std::vector<A<43>> vec_a;
    doSomething(vec_a); //FAIL: "no matching function for call to 'doSomething'
                        //      "candidate template ignored: could not match N against 'A<43>'"
    return 0;
}

我理解,编译器尝试将其与A&lt; 43&gt;绑定,而不是将N与43绑定。 (这是有意义的,因为vec_a的类型为std::vector<A<43>>,而不是类型std::vector<A><43>或类似的东西),并且在逻辑上无法这样做。

我该怎么办? (编译器:clang ++ 3.3)

2 个答案:

答案 0 :(得分:0)

您可以添加第二个接受矢量的重载:

#include <vector>

template <typename T, typename A>
void doSomething(std::vector<T, A> const & v)
{
    doSomething(v[3]);
};

正文将调用另一个模板,并假设该向量至少有四个元素。用你认为合适的逻辑替换它。

答案 1 :(得分:0)

显然有几种方法可以解决这个问题,但没有一种方法是完美的。

完美的方法是使用别名,即

template<int N> using Vec_A = std::vector<A<N>>
Vec_A<43> vec_a;
doSomething(vec_a); //Error!

但是别名只是一种速记,似乎很快就会被真实类型所取代。这至少是clang ++的情况,而不是GCC。该标准似乎与clang一致(见Grizzly评论)。

另一种方式当然是超载(参见Kerrek SB答案),但我发现它很难看:对我来说,它失败了使用模板的重点。

最后一种可能性,我更喜欢这里(但我不建议作为一个 默认)是公共继承:

template<int N> class Vec_A : public std::vector<A<N>> {};

它几乎是一个别名,除了更强的输入(不能再转换为矢量),在这种情况下对我来说没问题。