有什么好的方法可以做到以下这些吗?
/* vvv */
template<typename Wrapper> using T = typename Wrapper::type
T f(const T &a, const T &b) {
return a + b;
}
其中Wrapper
是一个包含(几个)类型的类。
我可以这样做,但我不喜欢这种方法,因为它使函数有几个模板类型(也没有完全相同的含义):
template<typename Wrapper, typename T = typename Wrapper::type>
T f(..)
我想这样做纯粹是为了减少在函数声明中键入typename Wrapper::type
的样板文件。如果有更好的方法,请告诉我。
注意:在我的项目中,Wrapper
类型需要满足一些概念,这也需要在Wrapper
类型中定义type
类型。
如果它可能有帮助,这里是我的用例。我正在(尝试)写一个线性代数库。在这个场景中,为了创建诸如向量或矩阵之类的对象,我们需要提供一个字段F,必须满足:
- F在某种基本类型T上(例如
F::type
) - F提供了两个操作
OpAdd
和OpMul
,这两个操作都可以在T
上操作。
使用概念定义它很简单,但是这会增加一些混乱,例如上面的例子。
你知道是什么类型吗?如果是这样,可以提供模板参数:
template<class T>
using inner = typename T::type;
template<class T>
inner<T> f(inner<T> const& a, inner<T> const& b);
// ...
f<X>(y, y);
在被请求的情况下,你不喜欢的是唯一的解决方案
#include <type_traits>
template<typename Wrapper,
typename T = typename Wrapper::type,
typename std::enable_if<std::is_same<T, typename Wrapper::type>::value>::type* = nullptr>
T f(const T &a, const T &b) {
return a + b;
}
struct S {
typedef long type;
};
int main() {
f<S>(0L, 0L); // ok
// f<S>(0, 0); // failure
// If the second type is set explicitly
f<S, long>(0L, 0L); // ok
f<S, long>(0, 0); // ok
// f<S, int>(0L, 0L); // failure
// f<S, int>(0, 0); // failure
}
这是一个比inner<T>
更好的解决方案,因为f<S>(0, 0)
不会在inner<T>
上失败-需要确切的long
,但int
通过了。