c++中的字符串模板参数
String template parameters in c++
在c++中使用模板时,有时需要将字符串作为值模板参数传递。
我发现很难理解为什么某些参数是允许的,而其他参数是不允许的。
例如,如果类的静态成员是const char*,则可以将其作为模板参数,如果在外部定义则不能。
我做了一个小程序来测试这一切,对没有编译的行进行注释。我也做了一些基于编译器输出的假设,但它们可能是错误的。
模板参数值的规则是什么。我看到对象需要外部链接,但bool是授权的,尽管它显然没有任何类型的链接。
#include <iostream>
using namespace std;
struct tag {
static char array[];
static const char carray[];
static char *ptr;
static const char *cptr;
static const char *const cptrc;
static string str;
static const string cstr;
};
char tag::array[] = "array";
const char tag::carray[] = "carray";
char *tag::ptr = (char*)"ptr"; // cast because deprecated conversion
const char *tag::cptr = "cptr";
const char *const tag::cptrc = "cptrc";
string tag::str = "str";
const string tag::cstr = "cstr";
namespace ntag {
char array[] = "array";
const char carray[] = "carray";
char *ptr = (char *)"ptr"; // cast because deprecated conversion
const char *cptr = "cptr";
const char *const cptrc = "cptrc";
string str = "str";
const string cstr = "cstr";
};
template <class T, T t>
void print() { cout << t << endl; };
int main()
{
cout << "-- class --" << endl;
// Works
print<char *, tag::array>();
print<const char *, tag::carray>();
// Does not work because it is a lvalue ?
// print<char *, tag::ptr>();
// print<const char *, tag::cptr>();
// print<const char *const, tag::cptrc>();
// Template type param must be a basic type ?
// print<string, tag::str>();
// print<const string*, tag::cstr>();
cout << "-- namespace --" << endl;
// Works
print<char *, ntag::array>();
// No external linkage ?
// print<const char *, ntag::carray>();
// Does not work because it is an lvalue ?
// print<char *, ntag::ptr>();
// print<const char *, ntag::cptr>();
// print<const char *const, ntag::cptrc>();
// The type of a template value param must a basic type
// print<string, ntag::str>();
// print<const string*, ntag::cstr>();
}
使用非类型模板参数时,需要指定一个常量。当非类型模板参数是指针或引用时,指定一个可以在链接时确定的常量就足够了。在任何情况下,编译器都不会接受任何可能在链接时间后发生变化的内容。即使是在链接时间初始化的变量也初始化得太晚:
print<char *, tag::array>(); // OK: the address of the array won't change
print<const char *, tag::carray>(); // OK: the address of the array won't change
print<char *, tag::ptr>(); // not OK: tag::ptr can change
print<const char *, tag::cptr>(); // not OK: tag::ptr can change
print<const char *const, tag::cptrc>(); // not OK: a [run-time initialized] variable
print<string, tag::str>(); // not OK: few types are supported (*)
print<const string*, tag::cstr>(); // not OK: tag::cstr has a different type
print<const string*, &tag::cstr>(); // (added) OK: address won't change
print<char *, ntag::array>(); // OK: address of array won't change
print<const char *, ntag::carray>(); // OK: address of array won't change (**)
print<char *, ntag::ptr>(); // not OK: ntag::ptr can change
print<const char *, ntag::cptr>(); // not OK: ntag::cptr can change
print<const char *const, ntag::cptrc>(); // not OK: a [run-time initialized] variable
print<string, ntag::str>(); // not OK: few types are supported (*)
print<const string*, ntag::cstr>(); // not OK: ntag::cstr has a different type
print<const string*, &ntag::cstr>(); // (added) OK: address won't change
注:
- (*)只有整型、指针和引用才能用作非类型模板参数。没有可以用作模板参数的用户定义常量的概念
(**)gcc不喜欢这个用法,而clang喜欢它。gcc不接受这个代码似乎是个错误!我看不到任何限制会禁止使用
const char[]
作为模板参数。相反,14.3.2【temp.arg.notype】第2段中有一个完全等效的示例:template<class T, const char* p> class X { / ... / }; X<int, "Studebaker"> x1; // error: string literal as template-argument const char p[] = "Vivisectionist"; X<int,p> x2; // OK
- 将字符串文字转换为指向
char
的非const
指针是可以的,但是,尝试更改其中一个值是未定义的行为。我强烈建议而不是使用此演员阵容 - 不要过度使用
std::endl
:在您的代码中,根本没有使用std::endl
相关文章:
- 如何使用Luacneneneba API正确读取字符串和表参数
- 如何使用字符串文字作为宏参数
- 如何将可变长度参数联接为字符串
- 如何使用字符串find_first_of缓冲区形式(size_t n 参数)
- 具有字符串化的可变参数宏的现代/通用方法
- C++ 构造函数参数:字符串、整数、整数、整数
- 当C 中的系统调用conconculables时,参数字符串中的字符损失
- 模板参数字符串与整数
- #define 参数字符串化,但宽字符串 L " instead of "
- std::getline 用于 ifstream,使用参数字符串或 char *
- 通过参数字符串化宏调用模板函数
- 可变参数字符串比较
- 为什么位集的构造函数有参数字符串::charT 零,字符串::charT one)
- c++中stdbind在带有参数(字符串)的函数中的用法
- 当使用字符变量作为参数(字符串转换为字符)时,Std::rename()文件将不起作用
- C/ c++预处理器中的宏参数字符串化为宽字符串字面值
- 如何比较Visual C++中的参数字符串
- C++错误:推断出参数'T'字符串与常量字符的冲突类型 *
- 传递参数字符串,其中包含空格和引号
- 函数参数字符串通过引用传递