代码在 gcc 上编译,但不在 msvc 上

Posted

技术标签:

【中文标题】代码在 gcc 上编译,但不在 msvc 上【英文标题】:Code compiling on gcc, but not on msvc 【发布时间】:2012-06-14 11:28:59 【问题描述】:

我在使用 msvc-2010 编译模板时遇到问题。它使用 gcc 4.6.3 完美运行。

我已经将代码归结为最重要的部分(当然没有意义):

//Variant that works
template <typename T, T* Ptr>
void callFun()



//Traits class (type expands to the same type T* as above)
template <typename T>
class TraitsClass

public:
    typedef T* type;
;

//Essentially the same as callFun2, only that the
//type of Ptr is expressed indirectly over a traits class
//The usage of this class is not possible, because of the error described below
template <typename T, typename TraitsClass<T>::type Ptr>
void callFun2()



//Provides a compile constant ptr for this example
void testFun()



int main()

    //Works
    callFun<void(), &testFun>();

    //Fails
    callFun2<void(), &testFun>();

    //Works
    callFun2<void(), 0>();

    return 0;

错误:

error C2975: 'Ptr' : invalid template argument for 'callFun2', expected compile-time constant expression

我发现它很有趣,它仅在通过 Traits 类中的 typedef 使用第二个类型参数时才会失败。 即使使用 -Wall -Wextra -Werror -pedantic,g++ 也可以正确编译此示例而不会出现警告(当然,未使用的参数除外)

非常感谢。

【问题讨论】:

我的猜测是 MSVC 期望 typename 引入类型参数,但这里 Ptr 是非类型参数。不过,模板参数的语法并不方便。 好主意,但不幸的是它似乎与此无关。有一个错误甚至暗示应该使用 typename 关键字。这对我来说确实有意义,因为 T* 确实是一种类型。 我会让情况更糟:这也不起作用://适用的变体 template void callFun() callFun2(); 【参考方案1】:

嗯,我认为答案是编译器不是上帝写的。编译器行业的编程标准非常高,MS C++ 是一个很好的编译器,但它仍然包含错误。我遇到了以下内容,这与您所指的内容有些相似:

template <class item_struct>
struct THeapBasedArray

    void  Sort(int (__cdecl *compareFunction)(const item_struct *item1,
                                              const item_struct *item2));
;

struct Item  int x; ;

struct ItemPtrsArray : public THeapBasedArray<Item*>

    static int __cdecl  Compare1(const Item **pp1, const Item **pp2);

    typedef Item *ItemPtr;
    static int __cdecl  Compare2(const ItemPtr *pp1, const ItemPtr *pp2);
;

int main()

    ItemPtrsArray vect;

    vect.Sort(ItemPtrsArray::Compare1);
    vect.Sort(ItemPtrsArray::Compare2);

第一次调用 Sort 失败:

cpptest1.cxx(21) : 错误 C2664: 'THeapBasedArray::Sort' : 无法将参数 1 从 'int (_cdecl *)(const Item **, const Item **)' 转换为 'int (_cdecl *)(const item_struct *, const item_struct *)

虽然第二次调用编译器很好。对我来说,这是编译器中的一个错误。有时会发生这种情况。我想这就是答案。

【讨论】:

我不认为这个例子与我的问题有任何关系。我希望每个编译器都会给出像您发布的那样的错误。还是我监督了什么? 编译器的抱怨是正确的,因为ItemPtrsArray::Compare1()ItemPtrsArray::Compare2() 这两个函数 相同。 Herb Sutter 在他的“与大师的对话”系列中就这个主题写了一篇有趣的文章。 drdobbs.com/conversationsa-midsummer-nights-madness/184403835 TLDR - 你永远不应该说 typedef Item *ItemPtr 正是因为它确实引入了这种潜在的错误。听从 Herb 文章中引用的伟大先知 Dan Saks 的建议,你的错误就会一目了然。

以上是关于代码在 gcc 上编译,但不在 msvc 上的主要内容,如果未能解决你的问题,请参考以下文章

没有前向声明的嵌套函数模板实例化可以在 GCC 上编译,但不能在 clang 上编译

无法在 MSVC 19.28 上编译变体访问者访问

GCC/MingW 在不同版本上编译

GCC 在尝试在 OSX 10.6 上编译 64 位代码时死了

haskell 代码可以在 leksah 上编译,但不能在 ghc 上编译

C++/LapackE 代码在 Windows 上编译良好,但相同的代码在 Linux 上编译失败