在 C++03 中将指针模板和指向成员函数的指针作为模板参数
Having Pointer Template and Pointer To Member Function as Template Arguments in C++03
我想用 2 个模板参数定义模板 class:
- 指针类型T*
- 指向基础类型 T 的成员函数的指针
此外,我想为函数参数设置一个默认方法。
// Do not allow SortedLinkedList<T>
template<typename T, bool (T::* comparisonMethod)(const T&) = &T::lessEqual>
class SortedLinkedList
{
private:
SortedLinkedList();
};
// Allow SortedLinkedList<T*>
template<typename T, bool (T::* comparisonMethod)(const T&)>
class SortedLinkedList<T*>
{
public:
void insert(T* item)
{
// do something with /item->*comparisonMethod)(...))
}
};
此代码无法编译,因为 g++ (4.4.3) 无法推导出 T*
的基础类型
错误:创建指向非class类型‘T*’
成员函数的指针
有没有办法推断出 class 声明中已有的基础类型? decltype
在 C++03 中不可用,我不知道它是否适用于这个地方。
我找到了 this answer,但在这种情况下没有帮助。
谢谢
问题
它编译失败的原因是编译器会检查 主模板 是一个可行的匹配 before 它继续查看是否有任何 specialization 是更合适的选择。
这意味着当您尝试实例化 SortedLinkedList<A*>
时,编译器会尝试查看 primary-template 中的声明 bool (T::* comparisonMethod)(const T&) = &T::lessEqual
是否是格式良好的 T = A*
- 显然不是(因为指针不能有成员函数)。
一个解决方案
解决此问题的一种方法是添加一个间接级别,以便主模板和专业化都产生格式良好的实例化。
template<class T> struct remove_pointer { typedef T type; };
template<class T> struct remove_pointer<T*> { typedef T type; };
template<class T>
struct comparison_method_helper {
typedef typename remove_pointer<T>::type Tx;
typedef bool (Tx::*type)(Tx const&) const;
};
// primary-template
template<
class T,
typename comparison_method_helper<T>::type = &remove_pointer<T>::type::lessEqual
> class SortedLinkedList;
// specialization
template<typename T, typename comparison_method_helper<T>::type func>
class SortedLinkedList<T*, func> {
public:
void insert (T const& item) {
(item.*func) (T ());
}
};
#include <iostream>
struct A {
bool lessEqual (A const&) const {
std::cerr << "hello world\n";
return false;
}
};
int main () {
SortedLinkedList<A*> ().insert (A()); // outputs 'hello world'
}
我想用 2 个模板参数定义模板 class:
- 指针类型T*
- 指向基础类型 T 的成员函数的指针
此外,我想为函数参数设置一个默认方法。
// Do not allow SortedLinkedList<T>
template<typename T, bool (T::* comparisonMethod)(const T&) = &T::lessEqual>
class SortedLinkedList
{
private:
SortedLinkedList();
};
// Allow SortedLinkedList<T*>
template<typename T, bool (T::* comparisonMethod)(const T&)>
class SortedLinkedList<T*>
{
public:
void insert(T* item)
{
// do something with /item->*comparisonMethod)(...))
}
};
此代码无法编译,因为 g++ (4.4.3) 无法推导出 T*
错误:创建指向非class类型‘T*’成员函数的指针
有没有办法推断出 class 声明中已有的基础类型? decltype
在 C++03 中不可用,我不知道它是否适用于这个地方。
我找到了 this answer,但在这种情况下没有帮助。
谢谢
问题
它编译失败的原因是编译器会检查 主模板 是一个可行的匹配 before 它继续查看是否有任何 specialization 是更合适的选择。
这意味着当您尝试实例化 SortedLinkedList<A*>
时,编译器会尝试查看 primary-template 中的声明 bool (T::* comparisonMethod)(const T&) = &T::lessEqual
是否是格式良好的 T = A*
- 显然不是(因为指针不能有成员函数)。
一个解决方案
解决此问题的一种方法是添加一个间接级别,以便主模板和专业化都产生格式良好的实例化。
template<class T> struct remove_pointer { typedef T type; };
template<class T> struct remove_pointer<T*> { typedef T type; };
template<class T>
struct comparison_method_helper {
typedef typename remove_pointer<T>::type Tx;
typedef bool (Tx::*type)(Tx const&) const;
};
// primary-template
template<
class T,
typename comparison_method_helper<T>::type = &remove_pointer<T>::type::lessEqual
> class SortedLinkedList;
// specialization
template<typename T, typename comparison_method_helper<T>::type func>
class SortedLinkedList<T*, func> {
public:
void insert (T const& item) {
(item.*func) (T ());
}
};
#include <iostream>
struct A {
bool lessEqual (A const&) const {
std::cerr << "hello world\n";
return false;
}
};
int main () {
SortedLinkedList<A*> ().insert (A()); // outputs 'hello world'
}