使用左值引用作为非类型模板参数

时间:2014-09-30 15:39:24

标签: c++ templates

我读到允许以下类型作为非类型模板参数:

  • 整数类型
  • 枚举
  • ptr to objects / methods
  • 对对象/方法的左值引用
  • 的std :: nullptr_t

我不明白非常量指针或左值引用是如何被接受的?它们不应该是常量类型,以便在编译时识别它们吗?

显然我并不比标准更聪明,所以有人能给我看一个左值引用的例子,也许还有一个指针用作非模板参数吗?

2 个答案:

答案 0 :(得分:4)

这是一个将方法指针和左值引用都作为非类型模板参数的示例:

int delete_counter_1 = 0;
int delete_counter_2 = 0;

template<int& ctr>
void increment_counter() { ++ctr; }

template<void(*func)()>
class Deleter {
    public:
    ~Deleter() { func(); }
};

int main() {
    { /* Internal scope */
      Deleter<increment_counter<delete_counter_1>> a, b;
      Deleter<increment_counter<delete_counter_2>> c;
    }
    std::cout << "Counter1: " << delete_counter_1
              << "; Counter2: " << delete_counter_2
              << '\n';
    return 0;
}

coliru上查看。

关于Deleter类的有趣之处在于它没有实际的数据成员;它的析构函数可以直接内联而无需间接函数调用。

正如Dalibor Frivaldsky在评论中提到的那样,关键是(实例化)函数delete_counter<int&>和计数器本身在编译时已知固定地址,所以作为指针他们的价值是不变的。特别是,这仅适用于具有静态寿命的对象;自动(“堆栈分配”)对象不起作用,非静态类成员,静态对象(如上所述)和静态类成员也都可以。

答案 1 :(得分:0)

标准在14.3.2 [temp.arg.nontype]中非常清楚地解释了如果非类型模板参数是指针或引用,可以用作参数:

  
      
  • 一个常量表达式(5.19),用于指定具有静态存储持续时间的完整对象的地址   和外部或内部联系或具有外部或内部联系的功能,包括功能   模板和函数template-id但不包括非静态类成员,表示(忽略括号)   作为&amp; id-expression,其中id-expression是对象或函数的名称,除了   &安培;如果名称引用函数或数组,则可以省略,如果相应则应省略   template-parameter是一个引用;或
  •   
  • 一个求值为空指针值的常量表达式(4.10);或
  •   
  • 一个常量表达式,其值为null成员指针值(4.11);或
  •   
  • 指向成员的指针,如5.3.1所述;或
  •   
  • 类型为std :: nullptr_t
  • 的常量表达式