考虑以下工作代码:
#include <iostream>
template<typename T> struct Traits {};
template<typename T, typename A>
struct Traits<void(T::*)(A)>
{
typedef T Class;
typedef A Arg;
};
template<typename T, typename U, void(T::*MemFun)(U)>
void Builder()
{
std::cout << typeid(T).name() << std::endl;
std::cout << typeid(U).name() << std::endl;
std::cout << typeid(MemFun).name() << std::endl;
}
template<typename T, T arg>
void Builder()
{
return Builder<Traits<T>::Class,Traits<T>::Arg,arg>();
}
class Class
{
public:
void foo(int) { }
};
int main()
{
Builder<decltype(&Class::foo), &Class::foo>();
}
我希望能够做到这一点,以获得相同的结果,而不使用宏。
int main()
{
Builder<&Class::foo>();
}
我似乎无法创建一个模板,该指针将指针指向成员并推断出类型。有什么想法吗?指向成员的指针必须用作模板参数而不是函数参数,因为它用于创建模板函数(未显示)。
答案 0 :(得分:4)
无法完成。要拥有非类型模板参数,您必须提供类型。因此,要么将Builder限制为仅限一种特定类型,要么需要额外的参数(列表中的第一个),即第二个参数的类型。现在,如果你不愿意将成员指针用作constexpr ......这很简单。
template <typename T, typename M>
struct Builder {
M T::*ptr;
Builder( M T::*ptr ) : ptr(ptr) {}
};
template <typename T, typename M>
Builder<T,M> createBuilder( M T::*ptr ) {
return Builder<T,M>(ptr);
}
int main() {
auto bld = createBuilder( &Class::member );
}
答案 1 :(得分:3)
我花了一些时间尝试自己做类似的事情。
如果不使用函数Class::foo
的名称两次,我认为不可能。我的推理如下:
foo
的类型,我们必须使用decltype
或将foo
作为模板函数的参数foo
的constexpr-ness(允许将其用作模板参数)丢失foo
,因为它会遇到与上面相同的问题foo
两次即使在C ++ 11中,似乎没有“脏”宏技巧也无法逃脱......
答案 2 :(得分:0)
不幸的是,没有办法对非类型模板参数的类型进行类型推导。宏是这里唯一的选择。