我尝试了以下代码。
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)'可以使用'指向具有外部链接的对象的指针'的含义。我可以获得任何示例代码吗?
答案 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!";
}