类模版的实例化instantiation
When a class template is implicitly instantiated, each declaration of its members is instantiated as well, but the corresponding definitions are not.
#include "stdafx.h"
template <typename T>
class Safe {
};
template <int N>
class Danger {
public:
typedef char Block[N]; // would fail for N<=0
};
template <typename T, int N>
class Tricky {
public:
virtual ~Tricky() {
}
void no_body_here(Safe<T> = 3);
void inclass() {
Danger<N> no_boom_yet;
}
void error() { Danger<N> boom; }
//void unsafe(T (*p)[N]);
T operator->();
// virtual Safe
struct Nested {
Danger<N> pfew;
};
union { // anonymous union
int align;
Safe<T> anonymous;
//Danger
};
};
int main()
{
Tricky<int, -1> ab;
//ab.error();
system("pause");
}
显然N为负数的时候是非法的,但是“lazy instantiation”只对函数申明中的N实例化(参数),函数体中的N在程序调用该函数的时候才去实例化
所以unsafe函数如果不注释,是无法编译的,而error函数只要不去调用,仍然可以通过编译
Default function call arguments are considered separately when instantiating templates. Specifically, they are not instantiated unless there is a call to that function (or member function) that actually makes use of the default argument. If, on the other hand, that function is called with explicit arguments that override the default, then the default arguments are not instantiated.
. Similarly, had the member anonymous been declared with type Danger
匿名Union会被编译
In practice, the definitions of virtual members should also be provided; otherwise, linker errors are likely to occur. This may have been a problem if we had uncommented the declaration of the virtual member suspect() for which no definition was provided.
虚函数必须提供函数定义
#include
using namespace std;
template
void g(T& t)
{
t = 30;
cout<
void main()
{
//g(10);
}
编译通过,如果去掉注释,不过
#include
using namespace std;
template
void f(T t)
{
t = 5;
cout<< t * 3 <
template
void g(T& t)
{
t = 11;
cout<
void main()
{
int const seven = 7;
f(seven); // OK !nonreference parameter: T is int
g(seven); // error C2166: l-value specifies const object
}
由于g函数参数为reference,所以 const保留 ?
We still need to explore how argument-parameter matching proceeds. We describe it in terms of matching a type A (derived from the argument type) to a parameterized type P (derived from the parameter declaration). If the parameter is declared with a reference declarator, P is taken to be the type referenced, and A is the type of the argument. Otherwise, however, P is the declared parameter type, and A is obtained from the type of the argument by decaying [2] array and function types to pointer types, ignoring top-level const and volatile qualifiers.