为什么模板 类 的静态成员不是唯一的
Why are static members of template classes not unique
看看下面的代码:
#include <iostream>
template <typename T>
class Foo
{
public:
static T bar;
};
template <typename T> typename T Foo<T>::bar;
int main() {
std::cout << "Foo<int>::bar : " << &Foo<int>::bar << std::endl;
std::cout << "Foo<double>::bar : " << &Foo<double>::bar << std::endl;
return 0;
}
这将打印出 2 个不同的地址。我可以理解为什么在这种情况下,bar
是 T
类型,因此 Foo<T>
中不同 T 的实例化将为您提供不同的静态成员。但是,如果我们将 bar
更改为我们已知的类型(例如 static int bar
),则此 still happens.
为什么会这样?为什么不将 bar
重新用于多个模板实例化?我怎样才能在不同的实例化过程中只获得 1 个 bar
对象?
这里并没有什么令人惊讶的事情。
template <typename T>
class Foo
{
//...
};
不是class,它是一个模板来杜绝classes。这意味着 Foo<A>
与 Foo<B>
完全不同 class。因此,所有静态成员对于 different 实例化的 classes 都是唯一的——并且 class 模板相同的事实在这种情况下无关紧要,因为它是毕竟是模板,实例化的蓝图classes.
如果您希望所有不同类型的 Foo
共享一个共同的状态,那么您可以让它们从相同的基础 class 继承,并将共同的信息放在那里。这是一个非常简单的例子:
struct Foo_Base
{
static int bar;
};
int Foo_Base::bar = 10;
template<typename T>
struct Foo : Foo_Base {};
int main()
{
Foo<int> foo_i;
Foo<double> foo_d;
std::cout << foo_i.bar << "\n";
foo_i.bar += 10;
std::cout << foo_d.bar;
}
输出:
10
20
来自标准,$14.7/6 模板实例化和专业化 [temp.spec]
Each class template specialization instantiated from a template has its own copy of any static members.
Foo<int>
和 Foo<double>
是不相关的 类,即使它们是从同一个模板实例化的,并且它们将有自己的静态成员 bar
,甚至尽管它们的类型相同(例如,两者都是 int
)。
Foo<int>::bar
和 Foo<double>::bar
是两个不同的全局(静态可访问 class 级)变量。他们不一样。考虑这段代码:
template <typename T>
class Foo
{
public:
static T var1;
static int var2;
};
您认为 var2
的相对位置是什么(假设编译器将 var2
放在 var1
之后)?在一种情况下,它可能相对仅提前 1 个字节 (foo<char>
),但在其他数据类型的情况下提前 8 个字节。
看看下面的代码:
#include <iostream>
template <typename T>
class Foo
{
public:
static T bar;
};
template <typename T> typename T Foo<T>::bar;
int main() {
std::cout << "Foo<int>::bar : " << &Foo<int>::bar << std::endl;
std::cout << "Foo<double>::bar : " << &Foo<double>::bar << std::endl;
return 0;
}
这将打印出 2 个不同的地址。我可以理解为什么在这种情况下,bar
是 T
类型,因此 Foo<T>
中不同 T 的实例化将为您提供不同的静态成员。但是,如果我们将 bar
更改为我们已知的类型(例如 static int bar
),则此 still happens.
为什么会这样?为什么不将 bar
重新用于多个模板实例化?我怎样才能在不同的实例化过程中只获得 1 个 bar
对象?
这里并没有什么令人惊讶的事情。
template <typename T>
class Foo
{
//...
};
不是class,它是一个模板来杜绝classes。这意味着 Foo<A>
与 Foo<B>
完全不同 class。因此,所有静态成员对于 different 实例化的 classes 都是唯一的——并且 class 模板相同的事实在这种情况下无关紧要,因为它是毕竟是模板,实例化的蓝图classes.
如果您希望所有不同类型的 Foo
共享一个共同的状态,那么您可以让它们从相同的基础 class 继承,并将共同的信息放在那里。这是一个非常简单的例子:
struct Foo_Base
{
static int bar;
};
int Foo_Base::bar = 10;
template<typename T>
struct Foo : Foo_Base {};
int main()
{
Foo<int> foo_i;
Foo<double> foo_d;
std::cout << foo_i.bar << "\n";
foo_i.bar += 10;
std::cout << foo_d.bar;
}
输出:
10
20
来自标准,$14.7/6 模板实例化和专业化 [temp.spec]
Each class template specialization instantiated from a template has its own copy of any static members.
Foo<int>
和 Foo<double>
是不相关的 类,即使它们是从同一个模板实例化的,并且它们将有自己的静态成员 bar
,甚至尽管它们的类型相同(例如,两者都是 int
)。
Foo<int>::bar
和 Foo<double>::bar
是两个不同的全局(静态可访问 class 级)变量。他们不一样。考虑这段代码:
template <typename T>
class Foo
{
public:
static T var1;
static int var2;
};
您认为 var2
的相对位置是什么(假设编译器将 var2
放在 var1
之后)?在一种情况下,它可能相对仅提前 1 个字节 (foo<char>
),但在其他数据类型的情况下提前 8 个字节。