C++ 忽略C++;

C++ 忽略C++;,c++,templates,c++03,C++,Templates,C++03,如果我有课: template <typename T> class MyClass { // ... }; 对于某些构建选项,my_type_1与my_type_2相同,在其他情况下则不同。我如何确保在所有场景中编译上述内容?有没有办法忽略重复的实例化 您可以为配置定义预处理器标志,然后将模板放入#ifdef块中。不要专门化typedef,而是专门化相关的底层类型(如int)。这样,您可以按自己的喜好多次/几次键入def,并且始终可以获得所需的专门化。您可以找到另一种方法来显

如果我有课:

template <typename T>
class MyClass
{ 
 // ...
};

对于某些构建选项,
my_type_1
my_type_2
相同,在其他情况下则不同。我如何确保在所有场景中编译上述内容?有没有办法忽略重复的实例化

您可以为配置定义预处理器标志,然后将模板放入
#ifdef
块中。

不要专门化typedef,而是专门化相关的底层类型(如int)。这样,您可以按自己的喜好多次/几次键入def,并且始终可以获得所需的专门化。

您可以找到另一种方法来显式地实例化
模板,从而可以对其进行元编程

然后,不要每行执行一个实例化,而是将它们全部放在一个包中。在模板上运行n^2算法(在编译时)以消除重复(或者,老实说,您可能会跳过这一步:取决于您如何实例化模板,它可能不在乎)

类似这样,假设
Instantiate
实际实例化了作为第一个参数传入的模板上的列表:

#include <utility>
#include <type_traits>

template<typename T>
struct Test {};

template<typename... Ts>
struct types {};

template<template<typename>class Template, typename Types>
struct Instantiate {};

template<template<typename>class Template, typename T0, typename... Ts>
struct Instantiate<Template, types<T0, Ts...>>:
  Instantiate<Template, types<Ts...>>
{
  Template<T0>& unused();
};

template<typename U, typename Types>
struct prepend;

template<typename U, template<typename...>class pack, typename... Ts>
struct prepend< U, pack<Ts...> > {
  typedef pack<U, Ts...> types;
};
template<typename U, typename Types>
using Prepend = typename prepend<U, Types>::types;

template<typename U, typename Types, typename=void>
struct remove_type_from_types;
template<typename U, template<typename...>class pack>
struct remove_type_from_types<U, pack<>, void>
{
  typedef pack<> types;
};

template<typename U, template<typename...>class pack, typename T0, typename... Ts>
struct remove_type_from_types< U, pack<T0, Ts...>,
  typename std::enable_if< std::is_same<U, T0>::value >::type
>: remove_type_from_types< U, pack<Ts...> >
{};

template<typename U, template<typename...>class pack, typename T0, typename... Ts>
struct remove_type_from_types< U, pack<T0, Ts...>,
  typename std::enable_if< !std::is_same<U, T0>::value >::type
>
{
  typedef Prepend< T0, typename remove_type_from_types< U, pack<Ts...> >::types > types;
};

template<typename Types>
struct remove_duplicates {
  typedef Types types;
};

template<template<typename...>class pack, typename T0, typename... Ts>
struct remove_duplicates<pack<T0, Ts...>> {
private:
  typedef typename remove_type_from_types< T0, pack<Ts...> >::types filtered_tail;
  typedef typename remove_duplicates< filtered_tail >::types unique_tail;
public:
  typedef Prepend< T0, unique_tail > types;
};
template<typename Types>
using RemoveDuplicates = typename remove_duplicates<Types>::types;

static Instantiate<Test, RemoveDuplicates<types<int, double>> > unused;

int main() {

}
#包括
#包括
模板
结构测试{};
模板
结构类型{};
模板
结构实例化{};
模板
结构实例化:
实例化
{
模板&unused();
};
模板
结构前置;
模板
结构前置{
类型定义包类型;
};
模板
使用Prepend=typename Prepend::types;
模板
结构从类型中删除类型;
模板
结构从类型中删除类型
{
类型定义包类型;
};
模板
结构从\U类型中删除\U类型\U::type,则typename std::enable_
>:从\U类型
{};
模板
结构从\U类型中删除\U类型\U::类型
>
{
typedef Prepend类型;
};
模板
结构删除重复项{
类型定义类型;
};
模板
结构删除重复项{
私人:
typedef typename从_types中删除_type _::类型筛选_tail;
typedef typename删除重复项::types unique\u tail;
公众:
typedef Prepend类型;
};
模板
使用RemovedDuplicates=typename移除重复项::类型;
静态实例化未使用的;
int main(){
}
如前所述,由于我是如何实例化
模板的使用,您可能可以去掉整个消除重复位。我也不确定上面对每个
模板的使用是否足以实例化它(即,它不会以某种方式被优化掉,并且符号会被导出)


(递归深度在类型的数量上是
n
,而完成的总工作量在类型的数量上是
n^2
:我怀疑这对于任何合理数量的类型来说都是足够浅和足够快的。爱好者独特的类型移除是困难的,因为在裸类型上缺乏弱排序…

雅克挽救了我的时间。实际上,我有很多非类型模板函数,它们的参数在编译时根据一些“#define”进行计算。我不会预先知道它们的值,我想显式地实例化它们。但当它们发生冲突时,编译器将停止,并显示错误“复制…”。因此,我遵循了雅克的想法,制作了一个非常简单的版本。我把它贴在这里给可能感兴趣的人

文件1:instantiate.h

#ifndef INC_INSTANTIATE_H
#define INC_INSTANTIATE_H

#include <iostream>
#include <utility>
#include <type_traits>

using namespace std;

template<unsigned short base> void func();

template<unsigned short base>
struct test {
    test() {
        cout << "Class " << base << " instantiated.\n";
        func<base>();
    }
    void instantiate_me(){};
};

template<typename... Ts>
struct instances {};

template<typename Types>
struct Instantiate {};

template<typename T0, typename... Ts>
struct Instantiate<instances<T0, Ts...>> : Instantiate<instances<Ts...>>
{
    T0 unused;
};

#endif
\ifndef公司实例化
#定义INC_实例化
#包括
#包括
#包括
使用名称空间std;
模板void func();
模板
结构测试{
测试(){

cout使用外部模板语法可以解决此问题,例如:

 extern template int max (int, int);

就我个人而言,我将模板代码保存在标题中,并让编译器根据需要自动实例化它。我想在某些情况下,这可能会延长编译时间。这是一个不错的建议,但会破坏
typedef
的目的。如果类型发生更改,我将收到链接错误,这将至少需要几分钟才能找到答案t、 比我现在拥有的(+1)要好。这是很多定义!有时类型不是由配置定义的,但可以随配置而改变。例如,最近,另一个类使用的某个
TextureCord
类型是
Vec2f
typedef
,但被更改为
Vec3f
(已实例化)在XCode上导致编译错误。非常有趣。我也不确定模板在
实例化
结构中的使用是否足以显式实例化。我没有访问
C++11
编译器的权限,因此我无法测试它,但肯定会将其保存以供以后研究。这是一个非常聪明的方法!@samaursa如果
模板
使用是不够的,请执行菊花链调用。然后在导出的函数中调用没有任何人调用的底部函数。
模板
s将被实例化以导出该函数,稍后链接时导出的函数将被删除,但如果在其他地方使用,
模板
s可能不会…我尝试使用C++11,显然不起作用。实例化中的引用显然不执行显式实例化。不过这是个好主意。我也在寻找解决方案,使用宏非常无聊,对我的使用效率也不高。@brahmin作为另一个想法,做一个-
sizeof
。sizeof基本上需要实例化。@Yakk不知道ange为我做任何事情。我认为除了使用template:class Test之外,你不能显式实例化。而且显然需要在cpp文件中完成,不需要任何函数。恐怕这个问题没有解决方案。。
#ifndef INC_INSTANTIATE_H
#define INC_INSTANTIATE_H

#include <iostream>
#include <utility>
#include <type_traits>

using namespace std;

template<unsigned short base> void func();

template<unsigned short base>
struct test {
    test() {
        cout << "Class " << base << " instantiated.\n";
        func<base>();
    }
    void instantiate_me(){};
};

template<typename... Ts>
struct instances {};

template<typename Types>
struct Instantiate {};

template<typename T0, typename... Ts>
struct Instantiate<instances<T0, Ts...>> : Instantiate<instances<Ts...>>
{
    T0 unused;
};

#endif
#include <iostream>
#include "instantiate.h"

using namespace std;

static Instantiate<instances<test<1>, test<2>, test<3>, test<4>>> unused;

template<unsigned short base>
void func() {
    cout << "Function " << base << " instantiated.\n";
}

static int initialize() {
    unused.unused.instantiate_me();
    return 0;
}

static int dummy = initialize();
#include <iostream>
#include "instantiate.h"
using namespace std;

int main() {
    cout << "Good day commander!\n";
}
 extern template int max (int, int);