C++模板类 = 类型名
C++ template class = typename
template <class = typename T::type>
是什么意思?你能给我推荐一些描述这个的博客和规范吗?
问题最初来自对 cpp 参考的 sfinae 的解释
template <typename A>
struct B { typedef typename A::type type; };
template <
class T,
class = typename T::type, // SFINAE failure if T has no member type
class U = typename B<T>::type // hard error if T has no member type
// (guaranteed to not occur as of C++14)
> void foo (int);
首先,我将解释typename T::type
。这只是成员类型的访问。下面是访问成员类型的示例:
struct foo {
using bar = int;
};
int main() {
foo::bar var{};
// var has type int
}
那么为什么typename
呢?它只是意味着我们想要访问一个类型。由于我们在模板中并且T
是未知类型,因此foo::bar
也可能意味着访问静态变量。为了消除歧义,我们表示我们实际上希望通过显式键入typename
来访问类型。
好的,现在class =
是什么意思?
class =
的意思与typename =
相同。在声明模板类型参数时,我们使用class
或typename
引入:
template<typename A, typename B>
struct baz {};
但与C++中的任何参数一样,名称是可选的。我本可以写这个,以下内容是完全等效的:
template<typename, typename>
struct baz {};
另外,您知道在函数参数中,我们可以指定默认值吗?诸如此类:
void func(int a, int b = 42);
int main () {
func(10); // parameter b value is 42
// We are using default value
}
我们也可以省略参数名称:
void func(int, int = 42);
就像函数参数一样,模板参数可以省略其名称,并且可以具有默认值。
template<typename, typename = float>
struct baz {};
baz<int> b; // second parameter is float
将一切整合在一起
现在我们有这个声明:
template <
class T,
class = typename T::type, // SFINAE failure if T has no member type
class U = typename B<T>::type // hard error if T has no member type
// (guaranteed to not occur as of C++14)
> void foo (int);
在这里,我们声明一个函数,该函数将 int 作为参数,并具有三个模板参数。
拳头参数是一个简单的命名参数。名称T
,它是一个类型模板参数。第二个也是类型参数,但它没有名称。但是,它的默认值为T::type
,这是T
的成员类型。我们通过指定typename
来显式告诉编译器T::type
必须是T
的成员类型。第三个参数与第二个参数类似。
这就是 SFINAE 发挥作用的地方:当使用默认参数时,但作为成员类型不存在T::type
,如何为其分配第二个模板参数?我们不能。如果T::type
不存在,则无法分配第二个模板参数。但是编译器不会让它出错,而是简单地尝试另一个函数,因为有可能另一个函数是可调用的。
这与简单的重载非常相似。您具有f
功能。它需要一个float
参数,另一个需要std::string
的重载。想象一下,你打电话给f(9.4f)
.编译器是否因为无法从float
构造std::string
而阻塞?不!编译器并不愚蠢。它将尝试另一个重载,并将找到float
版本并调用它。在SFINAE中可以进行类似的类比。编译器不会停止,因为模板参数中存在一些需要未定义类型的重载。它将尝试另一个重载。
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 大量序列中核苷酸类型的快速计数
- 如何从C++中的依赖类型中获得它所依赖的类型
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如何获取std::result_of函数的返回类型
- 从父命名空间重载类型
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 访问者访问变体并返回不同类型时出错
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 模板元程序查找相似的连续类型名称
- 是否可以从int转换为enum类类型
- 构造函数正在调用一个使用当前类类型的函数
- 我应该使用什么来代替void作为变体中的替代类型之一
- 类中的字符串不命名类型