2

可能重复:
是否可以模拟模板<auto X>?

考虑以下工作代码:

#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>();
}

我似乎无法创建一个模板来获取成员的指针并推断出类型。有什么想法吗?指向成员的指针必须用作模板参数而不是函数参数,因为它用于创建模板函数(未显示)。

4

3 回答 3

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 );
}
于 2012-08-20T19:39:29.583 回答
3

我花了一些时间尝试自己做类似的事情。

我认为不使用Class::foo两次函数名称是不可能的。我的推理如下:

  • 要获得类型,foo我们必须使用decltypefoo作为模板函数的参数
  • 在上述任何一种情况下,foo(允许将其用作模板参数)的 constexpr-ness 都丢失了
  • 此外,我们不能foo在模板类或函数中“复制”,因为它会面临与上述相同的问题
  • 结论:我们必须foo在外部范围内键入两次

似乎没有“肮脏”的宏技巧就无法逃脱,即使在 C++11 中也是如此……

于 2012-08-20T19:09:45.133 回答
0

不幸的是,没有办法对非类型模板参数的类型进行类型推导。宏实际上是这里唯一的选择。

于 2012-08-20T18:56:05.250 回答