模板别名-问题(C++之旅)
我正在浏览 C++ 之旅中的模板别名。我无法理解下面的代码以及如何使用它?
template<typename T>
class Vector {
public:
using value_type = T;
}
这里他使用 value_type 作为 typename 'T' 的类型别名,为什么我们不能只使用 typename T,因为我们可以将任何类型传递给模板(即类 Vector)。模板需要什么别名?
template<typename C>
using Value_type = typename C::value_type;
这里 value_type 在 C 的范围内如何,即我们如何引用类型为 'C' 的 value_type,因为它在类“vector”内?这里的“value_type”是指一个向量吗?和 'Value_type' 是指 int::Vector 或 string::Vector 等。?
template<typename Container>
void algo(Container &c)
{
Vector<Value_type<Container>> vec;
}
这三个部分是如何联系起来的?
回答
为什么是会员别名?
考虑您Vector在其他一些通用代码中使用的实例化:
template <typename U>
void foo(const U& u);
Vector<int> v;
foo(v);
然后在里面foo我们需要通过一些箍来找出那T是int. foo只知道U哪个是Vector<int>。如果Vector<int>有value_type别名,那么访问它要简单得多:
template <typename U>
void foo(const U& u) {
using value_type = typename U::value_type;
//...
}
现在foo不需要关心U::value_type实际上是T参数,Vector并且对于不是模板实例化的类型也可以:
struct OtherVector {
using value_type = int;
};
OtherVector ov;
foo(ov);
无成员别名:“some hoops”
使用成员别名是一种简单的方法。为了完整起见,我想展现复杂的方式,可以让foo推断T的Vector<T>。你得忍受我...
首先,请注意函数模板不能部分特化。这就是为什么我引入了一个间接级别:
template <typename U>
struct foo_impl {
void operator()(const U& u) {
std::cout << "Hello n";
}
};
template <typename U>
void foo(const U& u) { foo_impl<U>{}(u); }
来电者会打电话foo,在后台我们可以乱搞foo_impl。例如,我们可以为Vector<T>我们可以直接访问的地方添加部分规范T:
template <typename T>
struct foo_impl< Vector<T> > {
void operator()(const Vector<T>& v) {
std::cout << "Hello Vector<T>n";
if constexpr (std::is_same_v<int,T>) {
std::cout << "T == intn";
}
}
};
现场示例。
但是,请考虑这对foo. 的foo上面是精细与具有任何类型的value_type别名。现在我们有一个相当乏味的一般定义 (prints "Hello") 和一个专门化Vector<T>(当 时打印更多T==int)。如果我们还想foo使用
template <typename T>
struct Bar {};
我们可以做什么?我们可以提供更通用的特化,它也匹配 的实例化Bar:
template <template<class> class A, class T>
struct foo_impl< A<T> > {
void operator()(const A<T>& v) {
std::cout << "Hello A<T>n";
if constexpr (std::is_same_v<int,T>) {
std::cout << "T == intn"; // We know what T is when a Vector<T> is passed !!
}
}
};
现场示例
它使用模板 tempalte 参数将模板的任何实例化与单个模板参数相匹配。
我们现在还好吗?不幸的是没有,因为假设我们想从中获得“值类型”:
template <typename A,typename B>
struct Moo {};
假设按照惯例,第一个参数A是我们要查找的值类型。然后我们需要添加一个更通用的专业化:
template <template<class...> class A, typename T,typename... Others>
struct foo_impl< A<T,Others...> > {
void operator()(const A<T,Others...>& v) {
std::cout << "Hello A<T>n";
if constexpr (std::is_same_v<int,T>) {
std::cout << "T == intn";
}
}
};
现场示例
这将匹配具有任意数量类型参数的模板实例,并将检测第一个模板参数为T.
我们还好吗?不幸的是:完全没有。以上不符合a
template <typename A, int x>
struct Omg {};
因为它有一个非类型模板参数。我们也可以解决这个问题,但让我们到此为止。无论如何,要求值类型始终是第一个参数太严格了。
TL; 博士
我们真正想要的是foo使用任何具有关联“值类型”的类型。做到这一点的简单方法是,任何类型都应该被传递给foo一个名为value_type.