我怎样才能使用g ++模仿MSVC ++的模板实例化行为?

时间:2011-06-20 23:14:08

标签: c++ templates visual-c++ g++

我正在尝试将我自己的lib从Visual Studio移植到GNU / Linux上的g ++,并且我在模板编译时遇到了一些问题。实际上,在Visual C ++中,只有在代码中明确使用模板时才会生成模板,而看起来(根据我的错误)g ++在首次使用模板之前会对模板的内容进行评估。这会导致以下错误:

error: incomplete type ‘X’ used in nested name specifier

...因为我在模板代码之后包含了一些类,而不是之前。我这样做是因为交叉使用冲突。

总之,似乎Visual C ++不会尝试在使用时解析模板的内容,而g ++会尽快解析。

class MyClass;
template<class _Ty>
void func(MyClass* a_pArg)
{ 
   a_pArg->foo();
};

(_ Ty未使用,但无关紧要,只是为了解释问题)

在这种情况下,Visual C ++将编译(即使MyClass未预先声明),而g ++不会,因为MyClass尚未完全声明。

有没有办法告诉g ++仅在使用时实例化模板?

4 个答案:

答案 0 :(得分:9)

不,这就是两阶段查找的工作方式。 MSVC实现它错误,它几乎跳过了第一阶段,它在定义点解析模板。 MSVC仅在此处执行一些基本语法检查。在第二阶段,在实际使用模板时,只应检查从属名称。 MSVC在这里进行所有类型的解析。 GCC正确实现了两阶段查找。

在您的情况下,由于MyClass不是模板参数,因此可以在第一阶段检查它。您只需要 来包含您的类标题。

答案 1 :(得分:1)

正如另一个答案所示,gcc在第一个查找阶段查找非依赖名称是正确的,VC ++将大多数检查转移到第二阶段(这是不正确的)。为了修复你的代码,你不需要搜索一些破解版的gcc。您需要将声明和实现分开(至少对于非依赖名称)。使用您的示例,

// provide declarations
class MyClass;

template<class T>
void func(MyClass* a_pArg);

// provide definition of MyClass
class MyClass
{
   // watever
};

// provide definition of func
template<class T>
void func(MyClass* a_pArg);
{ 
   a_pArg->foo();
};

答案 2 :(得分:1)

如果您愿意使用CLang而不是gcc,CLang支持-fdelayed-template(专用于在解析结束时执行模板实例化),-fms-extensions选项隐含专门用于编译MSVC代码(和许多怪癖。)

根据Francois Pichet的说法,他正在领导CLang全力编译MSVC代码(并且实际上正在完成大部分代码),CLang应该能够在大约2到3个月内解析所有MFC代码,只有几个非仍然存在重大问题。已经正确解释了大多数MFC(即,解释为VC ++)。

答案 3 :(得分:0)

Visual C ++默认情况下不会实现标准指定的两阶段查找。

但是,在使用/ Za选项的Visual Studio 2015中,看起来两阶段查找会更好一些。也许您可以通过添加/ Za选项来模拟GCC模板实例化行为,以便在某些情况下执行相反的操作。