TheRiver | blog

You have reached the world's edge, none but devils play past here

0%

模板特化

参考

Substitution failure is not an error

C++ Template的选择特化

C++模板进阶指南:SFINAE

std::enable_if

SFINAE

SFINAE

替换失败不是错误(SFINAE)是指C ++中模板参数的无效替换本身并不是错误的情况。David Vandevoorde首先引入了缩写词SFINAE来描述相关的编程技术。[1]

具体地,当创建用于重载解析的候选集时,该集合的一些(或全部)候选者可能是实例化模板的结果,该模板实例化了(可能推导的)模板参数来代替相应的模板参数。如果在将一组参数替换为任何给定模板的过程中发生错误,则编译器会从候选集中消除潜在的重载,而不会因编译错误而停止,前提是替换错误是C ++标准授予此类处理的错误。[2]如果剩下一个或多个候选并且重载解析成功,则调用格式正确

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct Test {
typedef int foo;
};

template <typename T>
void f(typename T::foo) {} // Definition #1

template <typename T>
void f(T) {} // Definition #2

int main() {
f<Test>(10); // Call #1.
f<int>(10); // Call #2. Without error (even though there is no int::foo)
// thanks to SFINAE.
}

此规则在函数模板的重载解析期间适用:当用显式指定的或推导的类型代替template参数失败时,将从重载集中放弃专业化,而不会引起编译错误。

替代发生在:

  • 函数类型中使用的所有类型(包括返回类型和所有参数的类型)
  • 模板参数声明中使用的所有类型

//(自C ++ 11起)

  • 函数类型中使用的所有表达式
  • 模板参数声明中使用的所有表达式

//自C ++ 20起)

  • 显式说明符中使用的所有表达式

模板特化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//typedef integral_constant<bool,true> true_type;
//template <class T, T v>
// struct integral_constant {
// static constexpr T value = v;
// typedef T value_type;
// typedef integral_constant<T,v> type;
// constexpr operator T() { return v; }
// };
#include <iostream>
struct mytrue {
public:
static const int value = 1;
};
struct myfalse {
public:
static const int value = 0;
};

template<typename T> // 主模板
struct dd{};

template<>
struct dd<std::false_type> : myfalse // 对 T = false_type 显式特化
{
};

template<>
struct dd<std::true_type> : mytrue // 对 T = true_type 显式特化
{
};

int main()
{
std::cout << dd<std::true_type>::value << std::endl;
std::cout << dd<std::false_type>::value << std::endl;
}

enable_if

1
2
3
4
5
6
7
8
9
10
11
// Define a nested type if some predicate holds.
// Primary template.
/// enable_if
template<bool, typename _Tp = void> //主模板
struct enable_if
{ };

// Partial specialization for true.
template<typename _Tp> //特化模板
struct enable_if<true, _Tp>
{ typedef _Tp type; };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>

template <bool, typename T = void> //主模板
struct my_if{};

template <typename T>
struct my_if<true, T>{ //特化模板
typedef T type;
};

template <typename T>
struct my_if<false, T>{ //特化模板
typedef T* type;
};

int main()
{
std::cout << std::is_same<void, my_if<true>::type>() << std::endl;
std::cout << std::is_same<void *, my_if<false>::type>() << std::endl;

std::cout << std::is_same<int, my_if<true, int>::type>() << std::endl;
std::cout << std::is_same<int *, my_if<false, int>::type>() << std::endl;
}

总结

模板特化和SFINAE挺复杂的,目前没有精力挖的太深,掌握大概就行了。

ending

2020071601.jpg

----------- ending -----------