考虑:
#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)
答案 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>> {};
它几乎是一个别名,除了更强的输入(不能再转换为矢量),在这种情况下对我来说没问题。