我一直在查看C++ 0x的N3291工作草案.我对extern模板感到好奇.第14.7.3节规定:
除了内联函数和类模板特化之外,显式实例化声明具有抑制它们引用的实体的隐式实例化的效果.
仅供参考:"明确的实例化声明"一词是标准的extern template
.这已在第14.7.2节中定义.
这听起来像是在说如果你使用extern template std::vector<int>
,那么做任何通常隐式实例化的事情std::vector<int>
都不会这样做.
下一段更有趣:
如果实体是同一翻译单元中的显式实例化声明和显式实例化定义的主题,则该定义应遵循声明.作为显式实例化声明的主体并且以在否则将导致翻译单元中的隐式实例化(14.7.1)的方式中使用的实体应该是程序中某处的显式实例化定义的主题; 否则该程序格式错误,无需诊断.
仅供参考:术语"显式实例化定义"是这些事物的标准说法:template std::vector<int>
.也就是说,没有了extern
.
对我来说,这两件事说extern template
防止了隐式实例化,但它并没有阻止显式实例化.所以,如果你这样做:
extern template std::vector<int>;
template std::vector<int>;
Run Code Online (Sandbox Code Playgroud)
第二行有效地否定了第一行,明确地做了第一行隐含发生的事情.
问题是:Visual Studio 2008似乎不同意.我想要使用的方法extern template
是阻止用户隐式实例化某些常用模板,以便我可以在.cpp文件中显式实例化它们以减少编译时间.模板只会实例化一次.
问题是我必须在VS2008中围绕它们#ifdef.因为如果单个翻译单元看到extern
和非extern
版本,它将使extern
版本获胜并且没有人会实例化它.然后是链接器错误.
所以,我的问题是:
extern template
防止明确的实例化吗?extern template
行为?c++ templates visual-studio-2008 explicit-instantiation c++11
请考虑以下头文件:
// Foo.h
class Foo {
public:
template <typename T>
void read(T& value);
};
Run Code Online (Sandbox Code Playgroud)
我想Foo::read
在源文件中显式实例化成员函数模板,包括在boost::mpl::vector
:
// Foo.cc
#include <boost/mpl/vector.hpp>
#include <boost/mpl/begin_end.hpp>
#include "Foo.h"
template <typename T>
void Foo::read(T& value) { /* do something */ }
typedef boost::mpl::vector<int, long, float> types;
// template Foo::read<int >(int&);
// template Foo::read<long >(long&);
// template Foo::read<float>(float&);
// instantiate automatically ???
Run Code Online (Sandbox Code Playgroud)
可能吗?谢谢,丹尼尔.
编辑
我找到了一些解决方案 - 似乎Foo::read<T>
在结构的构造函数中指定一个指针,然后声明该变量,导致实例化:
// intermezzo
template <typename T> struct Bar {
Bar<T>() {
void (Foo::*funPtr)(T&) = &Foo::read<T>; …
Run Code Online (Sandbox Code Playgroud) 我刚刚阅读有关模板显式实例化的内容:
template struct MyStruct<long>;
它被描述为"非常罕见",所以它在什么情况下会有用?
是否可以通过模板别名显式实例化模板类?
如果是这样,怎么样?否则,有人可以指向讨论和决定反对的ISO文件吗?
template<class T>
struct A { };
/// Explicit instantiate A for int:
template struct A<int>;
/// Alias
template<class T>
using B = A<T>;
/// Explicitly instantiate A for double via alias B:
template struct B<double>;
/// error: elaborated type refers to a non-tag type
Run Code Online (Sandbox Code Playgroud)
不应该实例化,A<double>
因为B<T>
它只是一个不同的名称A<T>
?
我不确定它是否是Clang 3.2中的错误或违反C++ 03,但似乎模板类的模板化构造函数的显式实例化失败,但模板类的模板化成员函数的显式实例化成功.
例如,以下编译没有clang ++和g ++的问题:
template<typename T>
class Foo
{
public:
template<typename S>
void Bar( const Foo<S>& foo )
{ }
};
template class Foo<int>;
template class Foo<float>;
template void Foo<int>::Bar( const Foo<int>& foo );
template void Foo<int>::Bar( const Foo<float>& foo );
template void Foo<float>::Bar( const Foo<int>& foo );
template void Foo<float>::Bar( const Foo<float>& foo );
Run Code Online (Sandbox Code Playgroud)
而以下编译没有使用g ++警告但使用clang ++失败:
template<typename T>
class Foo
{
public:
template<typename S>
Foo( const Foo<S>& foo )
{ }
};
template class Foo<int>;
template …
Run Code Online (Sandbox Code Playgroud) 我想知道为什么下面的代码在gcc中运行得很好
#include <iostream>
using namespace std;
template<typename T>
struct F {
static T const value;
};
template<>
struct F<int> { // Specialization
static int const value;
};
template struct F<int>;
template<typename T>
T const F<T>::value = sizeof(T);
template<>
int const F<int>::value = 42;
int main() {
struct F<int> ma;
cout << ma.value;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在MSVC 2012上我无法编译:
#include <iostream>
using namespace std;
template<typename T>
struct F {
static T const value;
};
template<>
struct F<int> { // Specialization
static …
Run Code Online (Sandbox Code Playgroud) c++ templates language-lawyer explicit-specialization explicit-instantiation
这个问题正在考虑模板类的明确实例化.
考虑B<T>
从另一个模板类派生的模板类A<T>
.我想明确地实例化,B<T>
因为它的方法是从动态链接调用的,所以这些方法必须实例化,尽管它们不是在代码本身中调用的.当然,也会调用从中继承的方法A<T>
,因此它们也必须实例化.
似乎C++在显式实例化模板类时不会实例化基类,如本问题所述: C++类模板的显式实例化是否实例化依赖基类? 例:
template<typename T>
class A{ void foo(){...} };
template<typename T>
class B : public A<T> {}
template class B<int>; // This will NOT instanciate A<int>::foo()!!!
Run Code Online (Sandbox Code Playgroud)
当然,我还需要实现所有基类.但是,我不想用此负担客户端代码,因为类层次结构可能非常深.考虑涉及10个或更多模板类的类层次结构.不应该敦促客户编写10个显式模板实例.这不仅仅是大量的写作; 当我向类层次结构引入更改时,它也会中断.
相反,我想以某种方式实现无论何时实现B<T>
,那么它的所有基类都是如此.我尝试简单地在B本身中实现基类,如下所示:
template<typename T>
class B : public A<T> {
template class A<T>; // Does not compile!
}
Run Code Online (Sandbox Code Playgroud)
但这不编译.还有其他方法可以实现这一目标吗?
I am using the glm
library, which is a header-only collection of math utilities intended for 3D graphics. By using -ftime-trace
on Clang and ClangBuildAnalyzer
, I've noticed that a lot of time is being spent instantiating glm
types:
**** Templates that took longest to instantiate:
16872 ms: glm::vec<4, signed char, glm::packed_highp> (78 times, avg 216 ms)
15675 ms: glm::vec<4, unsigned char, glm::packed_highp> (78 times, avg 200 ms)
15578 ms: glm::vec<4, float, glm::packed_highp> (78 times, avg 199 ms)
... …
Run Code Online (Sandbox Code Playgroud) G++ 和 Clang++ 同意以下代码段不是有效的 C++:
template<int dim, int rank>
struct Tensor {};
template<int dim>
double InnerProduct(Tensor<dim, 1> const &, Tensor<dim, 1> const &)
{ return 0.0; }
template<int dim>
double DoubleInnerProduct(Tensor<dim, 2> const &, Tensor<dim, 2> const &)
{ return 0.0; }
template<int dim, int rank>
class Field
{
private:
static double Dot(Tensor<dim, rank> const &u, Tensor<dim, rank> const &v) requires (rank == 1)
{ return InnerProduct(u, v); }
static double Dot(Tensor<dim, rank> const &u, Tensor<dim, rank> const &v) requires …
Run Code Online (Sandbox Code Playgroud) c++ language-lawyer explicit-instantiation c++-concepts c++20
这有效并输出“1”,因为函数的约束是部分排序的并且最受约束的重载获胜:
template<class T>
struct B {
int f() requires std::same_as<T, int> {
return 0;
}
int f() requires (std::same_as<T, int> && !std::same_as<T, char>) {
return 1;
}
};
int main() {
std::cout << B<int>{}.f();
}
Run Code Online (Sandbox Code Playgroud)
这也有效,因为显式实例化不会实例化不满足约束的成员函数:
template<class T>
struct B {
int f() requires std::same_as<T, int> {
return 0;
}
int f() requires (!std::same_as<T, int>) {
return 1;
}
};
template struct B<int>;
Run Code Online (Sandbox Code Playgroud)
那么这个应该怎么办呢?
template<class T>
struct B {
int f() requires std::same_as<T, int> {
return …
Run Code Online (Sandbox Code Playgroud) c++ language-lawyer explicit-instantiation c++-concepts c++20