【问题标题】:"Invalid template argument" error in Visual Studio but not GCCVisual Studio 中的“无效的模板参数”错误,但不是 GCC
【发布时间】:2011-07-15 23:13:11
【问题描述】:

假设你有代码

template <template<class> class BaseType>
class EST16
    : public BaseType<int>
{
public:
    EST16(double d) 
    {
    }
};

template <class T>
class SCEST
{
    T y;
};
typedef EST16<SCEST> EST16_SC;
class Child
    : public EST16_SC
{
public:
    Child()
        : EST16_SC(1.0)
    {
    }

};



class NotWorkingChild
    : public EST16<SCEST>
{
public:
    NotWorkingChild()
        : EST16<SCEST>(1.0)
    {
    }

};



TEST(TemplateTest, TestInstantiate)
{
    Child child;
    NotWorkingChild notWorkingChild; 
}

Child 和 NotWorkingChild 的区别仅在于 typedef。在 GCC 中都编译,在 Visual Studio 中 NotWorkingChild 的构造函数会产生以下错误:

2>..\..\..\src\itenav\test\SCKFErrorStateTest.cpp(43) : error C3200: 'SCEST<T>' : invalid template argument for template parameter 'BaseType', expected a class template
2>        with
2>        [
2>            T=int
2>        ]

你能解释一下为什么会这样吗?有没有比 typedef 更好的便携解决方案?

谢谢!

【问题讨论】:

  • 您是否编写过任何实际实例化和使用模板类的代码?我的意思是,比如说,main。可能发生的一件事是 VCC 在看到 typedef 时会测试实例化,而 GCC 在实际使用您的子类之一之前不会打扰。如果这是真的,那么一旦您实际编写使用子类模板之一的代码,您也会在 GCC 中遇到错误。
  • 是的,我做到了。 TEST 宏创建了一个 Google 测试,它实际上是从 main() 调用的。
  • 抱歉 -- TEST 宏就在我的滚动截止之后,所以我错过了它。我不是 100% 为什么会失败,但我在下面发布了一种替代方法,它应该更易于跨编译器移植。在我看来,它也更具可读性:)

标签: c++ visual-studio templates gcc


【解决方案1】:

错误消息是因为NotWorkingChild(间接)派生​​自SCEST&lt;int&gt;,这使得SCESTNotWorkingChild 范围内引用类SCEST&lt;int&gt;,而不是模板。 MSVC 拒绝这个是正确的,GCC4.5 也应该拒绝这个(GCC4.5 有更正确的注入类名查找)。

这是一个可能适用于两种编译器的解决方案

class NotWorkingChild
    : public EST16<SCEST>
{
public:
    NotWorkingChild()
        : EST16< ::SCEST >(1.0)
    {
    }

};

请注意,我们使用范围解析运算符并且需要在:: 之前放置一个空格(否则标记&lt;: 将被视为有向图)。


突发新闻:即使您执行EST16&lt;SCEST&gt;,C++0x 也会使上述工作正常进行。原因是,它表示如果将注入的类名传递给模板模板参数,则注入的类名将被视为模板,而不是类型。因此,对于 C++0x,GCC 将是正确执行此操作的编译器。

【讨论】:

  • 似乎 VS "14" CTP 仍然需要范围解析运算符。
【解决方案2】:

如果您将初始化程序更改为仅引用模板类名 EST16,它将在 VS 上编译。即:

class NotWorkingChild : public EST16<SCEST>
{
public:
    NotWorkingChild()
        : EST16(1.0)
    {
    }
};

【讨论】:

  • 那是正确的,但我正在寻找一个可移植的解决方案,这不能用 GCC 编译:-(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-22
  • 2015-06-06
  • 2017-10-10
  • 1970-01-01
  • 1970-01-01
  • 2014-03-14
  • 1970-01-01
相关资源
最近更新 更多