字符串模板参数c

前端之家收集整理的这篇文章主要介绍了字符串模板参数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.nontype]段落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

>将字符串文字转换为非const指向char的指针是OK,但是,尝试更改其中一个值是未定义的行为.我强烈建议不要使用这个演员!
> Don’t overuse std::endl:在你的代码中,根本不用std :: endl.

猜你在找的C&C++相关文章