用户定义的非类型参数解决方法

时间:2016-06-01 01:19:28

标签: c++ templates lambda constexpr

前段时间我了解到你可以将文字传递给模板,如下所示:

template <int x>
class myClass { };

//Later
myClass<12> var;

现在我已经定义了我自己的int类型,并希望用它做同样的事情....但它结果是一个令人头疼的问题

我正在努力实现....这样的事情:

class myIntType;

template <myIntType val>
class Other{
};

不幸的是,这是非法的:(

所以另一个镜头是代替给出一个实际的实例,传递一个将返回一个实例的函数(因为这是一个整数类型反正....所以我们不关心实际上是两个实例相同的实例):

template<myIntTypeT(*Val)()>
class Other{
};

然后你就这样使用它:

constexpr myIntType foo() { return 12_mit; } 
   //_mit operator returns a myIntType var
Other<foo> other;

这种方法有几个缺点:

  • Other<foo>Other<bar>是不同的类型,即使bar反映foo给出的任何内容(我也很好)
  • 非常不优雅(我不太好)

不幸的是,这是一个非常笨重的用途。所以我的下一个尝试是采用lambda函数并将其放入模板中:

Other<[](){ return 12_mit; }> other;

但是失败了因为lambda不是constexpr s ....

还有另一个更优雅的解决方案是将用户定义类型的实例传递到模板中吗?

1 个答案:

答案 0 :(得分:1)

一种选择是将对MyIntType实例的引用作为模板参数传递:

class MyIntType {
public:
  MyIntType () {}
};

template <const MyIntType & val>
class Other {};

const MyIntType foo;

int main () {
  Other<foo> other;
}

另一种选择是将指针传递给MyIntType的实例作为模板参数:

class MyIntType {
public:
  MyIntType () {}
};

template <const MyIntType * val>
class Other {};

const MyIntType foo;

int main () {
  Other<&foo> other;
}

请注意,在这些简单示例中,MyIntType的构造函数不需要是constexpr

根据C ++标准(第14.3.2节,第1节):

  

非类型非模板模板参数 template-argument 应为以下之一:

     
      
  • 表示整数或枚举类型的非类型模板参数 template-parameter 类型的转换常量表达式(5.19);或

  •   
  • 非类型模板参数的名称;或

  •   
  • 一个常量表达式(5.19),用于指定具有静态存储持续时间和外部或内部链接的完整对象的地址,或具有外部或内部链接的函数,包括函数模板和函数 template-ids < / em>但不包括非静态类成员,表示(忽略括号)为 & id-expression ,其中 id-expression 是一个名称对象或函数,除了如果名称引用函数或数组可以省略&,如果相应的 template-parameter 是引用,则应省略; {或

  •   
  • 一个常量表达式,其值为空指针值(4.10);或

  •   
  • 一个常量表达式,其值为null成员指针值(4.11);或

  •   
  • 指向成员的指针,如5.3.1所述;或

  •   
  • 类型std::nullptr_t的常量表达式。

  •   

以上示例属于以下类别:

  

一个常量表达式,用于指定具有静态存储持续时间和外部或内部链接的完整对象的地址。