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

User Defined Non-Type Parameter Workaround

本文关键字:解决 方法 类型参数 定义 用户      更新时间:2023-10-16

不久前,我了解到您可以将文字传递到模板中,如下所示:

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 不是constexprs....

那么,是否有另一种更优雅的解决方案将用户定义类型的实例传递到模板中?

一种选择是对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 条):

类型、非模板模板参数的模板参数应为以下参数之一:

  • 对于整型或枚举类型的非类型模板参数,模板参数类型的转换常量表达式 (5.19);或

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

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

  • 计算结果为 null 指针值 (4.10) 的常量表达式;或

  • 计算结果为 null 成员指针值 (4.11) 的常量表达式;或

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

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

上述示例属于以下类别:

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