指向对象的指针,外部链接到Nontype模板参数

时间:2013-04-25 12:12:58

标签: c++ templates

我尝试了以下代码。

template <int VAL>
void printVAL()
{
    for(int i=0;i<VAL; i++){
        cout << " i value is "<<i<<endl;
    }
}

实例:     printVAL&LT; 100〕()

当我使用( std :: string s )作为非类型模板参数时,编译器对我大喊大叫,出现以下错误

"class std::basic_str<char>' is not a valid type for a template non-type parameter.

我所知道的是我们应该只使用常数积分值。甚至不加倍。

问题:

1)为什么我们不应该使用std :: string,有什么困扰?

2)'可以使用'指向具有外部链接的对象的指针'的含义。我可以获得任何示例代码吗?

4 个答案:

答案 0 :(得分:0)

有两种类型的模板:泛型类型的模板和指定类型的模板。

类似

的泛型类型的模板
template<typename T>

template<class T>

这些模板几乎可以与任何类型一起使用。这些类型的实际使用可能会限制可以使用的实际类型。

指定类型的模板与您在问题中的模板类似:

template<int VAL>

它们只能与匹配指定类型的模板参数一起使用。在这种情况下,只能使用整数文字。

答案 1 :(得分:0)

您只能将整数值作为非类型模板参数传递。这是语言的限制。您可能需要以下内容:

template<class T>
void printVAL(const T& t)
{
    for (auto& x : t) {
        cout << " x value is "<< x << '\n';
    }
}

这将打印任何东西:容器,字符串,数组等。

答案 2 :(得分:0)

根据14.1 / 4,

  

非类型模板参数应具有以下(可选的cv限定)类型之一:

     
      
  • 整数或枚举类型,
  •   
  • 指向对象或指向函数的指针,
  •   
  • 对对象的左值引用或对函数的左值引用,
  •   
  • 指向成员的指针,
  •   
  • std::nullptr_t
  •   

你的std::string不是那些。

答案 3 :(得分:0)

  

1)为什么我们不应该使用std :: string,有什么困扰?

编译器必须能够在编译时推断和替换模板参数。这不能用std::string对象完成,它可以(并且通常会)在运行时更改。

另见this Q&A

  

2)'可以使用'指向具有外部链接的对象的指针'的含义。我可以获得任何示例代码吗?

那是因为具有静态存储持续时间的对象的地址(声明为extern的对象是)是一个常量表达式。

n3337 5.19 / 3,强调我的:

  

文字常量表达式是文字类型的prvalue核心常量表达式,但不是指针类型。一个   integral constant expression是整数或未整数枚举类型的文字常量表达式。 [ 注意:   这些表达式可以用作数组边界(8.3.4,5.3.4),作为比特字段长度(9.6),作为枚举器初始化 -   如果底层类型没有固定(7.2),空指针常量(4.10)和对齐(7.6.2)。 -结束   注意] T类型的转换常量表达式是文字常量表达式,隐式转换为T类型,   其中隐式转换(如果有)在文字常量表达式和隐式转换中是允许的   序列仅包含用户定义的转换,左值到右值的转换(4.1),整数促销(4.5),   和整数转换(4.7),而不是缩小转换(8.5.4)。 [注意:可以使用这样的表达方式   作为case表达式(6.4.2),作为枚举器初始值设定项,如果基础类型是固定的(7.2),并作为整数或   枚举非类型模板参数(14.3)。 -end note]引用常量表达式是左值   核心常量表达式,用于指定具有静态存储持续时间或函数的对象。 一个地址   常量表达式是指针类型的prvalue核心常量表达式,其计算结果为地址   具有静态存储持续时间的对象,函数的地址,空指针值或prvalue核心   std :: nullptr_t类型的常量表达式。总的来说,文字常量表达式,引用常量   表达式和地址常量表达式称为常量表达式。

您要求的示例:

#include <iostream>
#include <string>

extern std::string str; // not really neccesary

std::string str;

template<std::string* ptr>
struct S {
    S() { std::cout << ptr->length() << '\n'; }
    ~S() { std::cout << *ptr; }
};

int main()
{
    S<&str> s;
    str = "Hello world!";
}