c++非类型模板参数(non-type template parameter)

无类型的模板参数:C++的template可以传入普通的参数,和平时使用普通的函数参数有点相似,但又有很大的不同。
这种形式的模板一般是用来初始化类的数组成员的大小例如下面有的代码:

template<int size>
class CTest
{
    int m_data[size];
};

void main()
{
    CTest<10> obj;// 将obj对象的成员 数值m_data大小初始为10 ,是不是很简单?
}

用整型来作为无类型模板参数使用起来确实easy,那么换其他类型试试?

收集了一点资料稍微整理了下,看看下面资料怎么说的:
a non-type template-parameter shall have one of the following types(无类型模板参数应该是下面所列举的类型):

  1. integral or enumeration type(整型 或者 枚举)
  2. pointer to object or pointer to function(对象的指针或函数指针,其实还包括基本类型的指针)
  3. reference to object (对象的引用或者函数的引用)
  4. Attention :The C++ standard does not allow floating point non-type template parameters
    (注意:c++标准规定浮点型不能作为无类型模板的参数 例如 float,double,但他们的引用和指针是允许的。)

你已经知道了应该传入什么类型参数,说真的,这还远远不够。
a template-argument for a non-type, non-template template-parameter shall be one of:

1.对于整型参数:应该传入一个常量或者枚举值
an integral constant-expression of integral or enumeration type

2.对象的指针或者函数的地址因该具有外部连接属性,否则将报错;
the address of an object or function with external linkage

3.可以是一个引用类型的参数参数 例如: template<int&> void func() {};
the corresponding template-parameter is a reference

下面再来看看non-type template-parameter 有关的错误描述:
error c2970:
an expression involving objects with internal linkage cannot be used as a non-type argument(涉及到对象内部连接的表达式不能作为 non-type argument)

error c2975:
expected compile-time constant expression(需要一个编译期常量表达式)

error c2971:
a local variable cannot be used as a non-type argument,You cannot use the name or address of a local variable as a template argument.(局部变量不能作为non-type argument,这里主要是指:指针和引用,但是局部整型常量除外,所以下面的代码是ok的。

下面是一些测试测试代码:

template<int>
void fun1()     {}

template<int*>
void fun1_1()   {}

template<int&>
void fun1_2()   {}

template<char*>
void fun2()     {}

template<char>
void fun3()     {}

struct  CA  {};
union   Ua  {};

// 浮点数 例如float,double,是不能作为 non-type template parameter的
//template<float>
//void fun4()   {}

// 要使用类的或者联合的指针 或者引用
//template<CA>            
//void fun4()   {}

//template<Ua>
//void fun5()   {}

template<CA*>         
void fun4_1()   {}

template<CA&>         
void fun4_2()   {}

template<Ua*>
void fun5_1()   {}

template<Ua&>
void fun5_2()   {}

//------------------------------------------------------------------------//
int         idata3 = 20;        // 外部链接
const int   idata2 = 9;         // 内部链接

CA          impCa1;             // 外部链接
const CA    impCa2;             // 内部链接
static CA   impCa3;             // 内部链接

Ua          impUa1;             // 外部链接
const Ua    impUa2;             // 内部链接
static Ua   impUa3;             // 内部链接

const char  str3[] = "str";       // 内部链接
static char str4[] = "str";       // 内部链接
char        str5[] = "str";       // 外部链接

char*       str6   = "str";       // 外部链接
const char* str7   = "str";       // 内部链接
char* const str8   = "str";       // 内部链接
const char* const str9   = "str"; // 内部链接

const char  chr    = 'x';     // 内部链接
void funtest(int);
void funtest( int )     {}

static void funtest2(int);
void funtest2( int )    {}

typedef void (*ptr_func)(int);

template<ptr_func>
void fun6()     {}

ptr_func pfun2 = &funtest;
const ptr_func pfun3 = &funtest;
static const ptr_func pfun4 = &funtest;

int _tmain(int argc, _TCHAR* argv[])
{

    int i = 12;
    //const int idata = i;  // error 2971 局部变量不能用作非类型参数
    const int idata = 10;   // 局部常量 ok
    fun1<idata>();            // ok

    int idata4 = 20;
    //fun1_1<&idata2>();  // error c2970 涉及到对象内部连接的表达式不能作为 non-type argument.
    //fun1_1<&idata4>();  // error c2971 
    fun1_1<&idata3>();        // ok

    //fun1_2<idata2>();       // error c2970
    //fun1_2<idata4>();       // error c2971 
    fun1_2<idata3>();     // ok

    char        str1[]  = "string";
    const char* str2    = "string";
    //fun2<str1>();           // error c2971
    //fun2<str2>();           // error c2971
    //fun2<str3>();           // error c2970 
    //fun2<str4>();           // error c2970
    //fun2<"test">();       // error c2762 模板参数的表达式无效,为什么会无效?字符串"test"具有内部链接? 问题1。
    fun2<str5>();         // ok
    //fun2<str6>();           // error 2975 需要一个编译期常量表达式
    //fun2<str7>();           // error 2975
    //fun2<str8>();           // error c2971
    //fun2<str9>();           // error c2971

    //fun3<str2[1]>();        // error 2975 需要一个编译期常量表达式
    //fun3<str3[0]>();        // error 2975 为什么str3[0]不是编译期常量,问题2
    fun3<'x'>();            // ok
    fun3<chr>();          // ok

    // ok
    fun4_1<&impCa1>();
    fun4_2<impCa1>();

    // ok
    fun5_1<&impUa1>();
    fun5_2<impUa1>();

    //
    ptr_func pfun = &funtest;
    //fun6<pfun>();       // error c2971
    //fun6<pfun2>();  // error c2975
    //fun6<pfun3>();  // error C2970
    //fun6<&pfun4>(); // error C2970
    fun6<&funtest>(); // ok
    fun6<&funtest2>();

        return 0;
}

https://www.cnblogs.com/lonely-little-boy/p/16726478.html#3_182

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部