Pet*_*der 47 c++ metaprogramming partial-specialization generic-programming
假设我想编写一个泛型函数void f<T>(),如果T是POD类型则执行一项操作,如果T是非POD(或任何其他任意谓词)则执行另一项操作.
实现此目的的一种方法是使用标签库调用模式,如标准库与迭代器类别一样:
template <bool> struct podness {};
typedef podness<true> pod_tag;
typedef podness<false> non_pod_tag;
template <typename T> void f2(T, pod_tag) { /* POD */ }
template <typename T> void f2(T, non_pod_tag) { /* non-POD */ }
template <typename T>
void f(T x)
{
// Dispatch to f2 based on tag.
f2(x, podness<std::is_pod<T>::value>());
}
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用部分专用类型的静态成员函数:
template <typename T, bool> struct f2;
template <typename T>
struct f2<T, true> { static void f(T) { /* POD */ } };
template <typename T>
struct f2<T, false> { static void f(T) { /* non-POD */ } };
template <typename T>
void f(T x)
{
// Select the correct partially specialised type.
f2<T, std::is_pod<T>::value>::f(x);
}
Run Code Online (Sandbox Code Playgroud)
使用一种方法比另一种方法有什么优缺点?你会推荐哪个?
Ale*_* C. 15
我喜欢的简单编译时调度的可读替代[boost|std]::enable_if,标记和部分特化如下:
[请记住,布尔值转换为整数,零长度数组无效,丢弃了违规模板(SFINAE).此外,char (*)[n]是一个指向n元素数组的指针.
template <typename T>
void foo(T, char (*)[is_pod<T>::value] = 0)
{
// POD
}
template <typename T>
void foo(T, char (*)[!is_pod<T>::value] = 0)
{
// Non POD
}
Run Code Online (Sandbox Code Playgroud)
它还具有不需要污染命名空间的外部类的优点.现在,如果你想在问题中外化谓词,你可以这样做:
template <bool what, typename T>
void foo(T, char (*)[what] = 0)
{
// taken when what is true
}
template <bool what, typename T>
void foo(T, char (*)[!what] = 0)
{
// taken when what is false
}
Run Code Online (Sandbox Code Playgroud)
用法:
foo<std::is_pod<T>::value>(some_variable);
Run Code Online (Sandbox Code Playgroud)