我想创建一个接受多个模板别名的模板函数。 这是一个更有意义的简单例子。
有模板别名 TAlias1和TAlias2
template <typename T>
using TAlias1 = TClass1<T, 2>;
template <typename T>
using TAlias2 = TClass2<T, 3>;
...然后我想创建一个接受上述任何别名的模板函数:
template <typename T, template<typename> class TClass>
TClass<T> someOperation(const TClass<T> &a, const TClass<T> &b)
{
...
}
int main()
{
TAlias1<float> a;
TAlias1<float> b;
TAlias1<float> c = someOperation(a,b);
return 0;
}
但是,它会导致Visual Studio 2013中的编译错误:
这种情况有解决办法吗?
修改
以下是产生错误的完整示例:
template <typename T, int I>
struct TClass1 {};
template <typename T, int I>
struct TClass2 {};
template <typename T>
using TAlias1 = TClass1<T, 2>;
template <typename T>
using TAlias2 = TClass2<T, 3>;
// this should accept TAlias1 and TAlias2
template <typename T, template<typename> class TClass>
TClass<T> someOperation(const TClass<T> &a, const TClass<T> &b) { return {}; }
int main()
{
TAlias1<float> a;
TAlias1<float> b;
TAlias1<float> c = someOperation(a,b);
TAlias2<float> d;
TAlias2<float> e;
TAlias2<float> f = someOperation(d,e);
return 0;
}
错误:
error C2784: 'TClass<T> someOperation(const TClass<T> &,const TClass<T> &)' : could not deduce template argument for 'const TClass<T> &' from 'TClass1<float,2>'
答案 0 :(得分:1)
这是错误的:
template <typename T, template<typename> class TClass>
TClass<T> someOperation(const TClass<T> &a, const TClass<T> &b)
如果没有以任何方式提供I
参数,编译器将如何解析?你需要做的是:
template <typename T, int I>
TClass<T, I> someOperation(const TClass<T, I> &a, const TClass<T, I> &b)
此功能适用于每个TClass
具体化。以下是您完整的工作示例:
template <typename T, int I>
struct TClass
{
public:
T value;
TClass<T,I> operator+(const TClass<T,I> &b) const
{
TClass<T, I> result;
result.value = value + b.value;
return result;
}
int getI()
{
return I;
}
};
template <typename T>
using TAlias1 = TClass<T, 2>;
template <typename T>
using TAlias2 = TClass<T, 3>;
// this should accept TAlias1 and TAlias2
template <typename T, int I>
TClass<T, I> someOperation(const TClass<T, I> &a, const TClass<T, I> &b)
{
return a+b;
}
int main()
{
TAlias1<float> a;
TAlias1<float> b;
TAlias1<float> c = someOperation(a,b);
return 0;
}
编辑。别名只是一个别名,而不是一个不同的类。该函数将接受所有TClass
个对象。您只能通过为每个别名创建部分专用函数来限制它:
template<typename T>
TAlias1<T> foo(TAlias1<T> a, TAlias1<T> b)
答案 1 :(得分:1)
我认为你想做的事情无法完成。
这应该有效:
TAlias1<float> c = someOperation<float, TAlias1>(a,b);
但是自动模板扣除失败,因为a
和b
实际上是TClass<float,2>
类型,并且与预期的模板参数不匹配。
是的,它们被声明为TAlias1<float
,它与预期的模板参数匹配,但是别名就是别名,它不是变量的真实类型,也不用于模板扣除
您可以尝试一些解决方法,例如:
template <typename T>
struct TAlias1 : TClass<T, 2> {};
但是你可能会遇到一些类型问题......
当然,您可以使用TClass
参数覆盖模板函数。其实我不确定你为什么不首先这样做......
答案 2 :(得分:1)
问题出在someOperation
函数的第二个模板参数中。模板别名不会引入新类型,它的工作方式类似于typedef。这意味着,即使TAlias1
只接受一个模板参数,它仍然是一个带有2个参数的模板(其中设置了第二个参数)。
事实上,如果你将功能更改为:
template <typename T, template<typename,int> class TClass>
TClass<T,2> someOperation(const TClass<T,2> &a, const TClass<T,2> &b)
{
return a+b;
}
它将编译(当然,你需要使operator+
const方法)。
更好的方法是不要将模板类用作第二个模板参数,并将函数更改为以下内容:
template <typename T1, typename T2>
auto someOperation(const T1 &a, const T2 &b) -> decltype(a+b)
{
return a+b;
}
或者甚至可能:
template <typename T>
T someOperation(const T &a, const T &b)
{
return a+b;
}