无类型的模板参数:
C++的template可以传入普通的参数,和平时使用普通的函数参数有点相似,但又有很大的不同。
这种形式的模板一般是用来初始化类的数组成员的大小例如下面有的代码:
template<int size>
class CTest {
int m_data[size];
};
void main() {
CTest<10> obj;// 将obj对象的成员 数值m_data大小初始为10 ,是不是很简单?
}
用整型来作为无类型模板参数使用起来确实simple,那么换其他类型试试?
收集了一点资料稍微整理了下,看看下面资料怎么说的:
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 or reference to function(对象的引用或者函数的引用)
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-type 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;
C++ 中 static 和 anonymouse namespace 的差别
记得以前一个同事问我为什么程序里使用了 anonymouse namespace ,想了想 就回答说其实就是保持局部性(这也是我的目的),然后就有人说为什么不用static,嗯 似乎这两个东西乍一看没什么区别,自己便Google了一下,发现有一个原因就是 anonymousenamespace 里的 member 都是有外部链接的,只不过永远都不能被外部link到!而 static 就明确为根本没有外部链接!此时就出现问题了,在模板里无类型的参数必须是有外部链接的才可以,否则编译无法通;比如:
template <void fn()>
class Foobar
{};
namespace
{
void abc()
{
wcout<<_T(”abc”)<<endl;
};
}
static void efg()
{
wcout<<_T(”efg”)<<endl;
};
int _tmain(int argc, _TCHAR* argv[])
{
Foobar<abc>xyz //! ;这一行可以通过
Foobar<efg>rst; //! 注意这一行编译不过
return 0;
}
也有人认为使用 anon namespace比较好,因为static的方式被C++98标准所批评,呵呵 总体来说 ,其实你完全可以用anony namespace代替static。