尝试使用未知类型的模板非类型参数

时间:2012-08-20 18:44:22

标签: c++ templates c++11 traits decltype

  

可能重复:
  Is it possible to emulate template<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>();
}

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

3 个答案:

答案 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)

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