为什么GCC找不到我的非模板功能? (“没有匹配函数来调用...”)

时间:2009-04-09 20:10:40

标签: gcc templates visual-c++

在MSVC 2008中,我有以下代码:

class Foo {
  //  Be a little smarter about deriving the vertex type, to save the user some typing.
  template<typename Vertex> inline void drawVertices(
    Elements vCount, RenPrim primitiveType, PixMaterial *mtl, Vertex const *vertices)
  {
    this->drawVertices(vCount, primitiveType, mtl, vertices, Vertex::VertexType);
  }

  virtual void drawVertices(
    Elements vCount,
    RenPrim primitiveType,
    PixMaterial *mtl,
    void const *vertices,
    uint vertexType) = 0;
};

我用的是:

struct RenFlexibleVertexPc
{
  enum { VertexType = RenVbufVertexComponentsPc };
  float x;
  float y;
  float z;
  GraVideoRgba8 c; // Video format, not external!
};


  PixMaterial *material;
  struct Pc : RenFlexibleVertexPc
          {
            void set(Triple t, uint cl) { x = (float)t.x_; y = (float)t.y_; z = (float)t.z_; c = cl; }
          } vpc[4];
  ...
  Foo *renderer;
  renderer->drawVertices(4, RenPrimTriangleFan, material, vpc);

这在MSVC 2008 SP1中运行良好。但是,GCC(3.4和4.1,2)会抛出“没有匹配的函数调用函数”错误,当存在具有更多参数的非模板函数时,显然没有看到模板。

GCC是否被破坏,或者我的代码是否被破坏,如果是,为什么?

3 个答案:

答案 0 :(得分:1)

重载或继承没有问题:

#include <iostream>
#include <memory>

namespace {
    struct A {
        virtual void f()
        {
            std::cout<<"inside A's f()\n";
        }

        template <typename T> void f(T t)
        {
            std::cout<<T::i<<'\t';
            this->f();
        }
    };

    struct B : A {
        void f()
        {
            std::cout<<"hello\t";
            A::f();
        }
    };

    struct C {
        static const unsigned int i = 5;
    };

    struct D {
        enum { i = 6 };
    };
}

int main()
{
    std::auto_ptr<A> b(new B());
    b->f(C());
    b->f(D());
}

正常工作。另一方面,我能找到的最能展示问题的例子没有继承或重载:

#include <iostream>

namespace {
    struct A {
        template<class C> void print(C c)
        {
            c.print();
        }
    };
}

int main()
{
    struct B {
        void print()
        {
            std::cout << "whee!\n";
        }
    };

    A a;
    B b;
    a.print(b);
}

请注意,如果在命名空间中定义struct B(无论是未命名的命名空间,还是完全不同的命名空间,还是全局命名空间),而不是在main()内部,则编译时没有错误。

我不知道该标准是否足够,如果这是一个bug,但它似乎是一个。我继续前进reported it to the GCC bug database


以下是GCC开发人员的回答(来自上面的链接):“本地类不能是模板参数。”

因此代码被破坏了。 Not that it's a bad idea。实际上,C ++ 0x删除了这个限制。

我注意到了这一行

  

请注意,如果我明确地将vpc转换为(RenFlexibleVertexPc *)

,则代码在GCC中有效

由于RenFlexibleVertexPc不是本地类,这是有道理的。但是Pc是本地类/结构,因此不允许使用。

答案 1 :(得分:1)

@OP:指定模板参数是一种有效的方法。

renderer->drawVertices<RenFlexibleVertexPc>(4, RenPrimTriangleFan, material, vpc);

随着Pete的增加,你的代码也编译在Apple的GCC 4.0.1上,所以我怀疑你发布的代码丢失了导致问题的原因。

@Max:GCC对您的来源的处理是标准的。结构B是main()的本地,所以B(因此main():: B :: print())在main()之外是不可见的。您可能已经意识到,将B的定义移到main()之外,它将进行编译。

答案 2 :(得分:0)

  

VertexType的定义已经在代码中(枚举)。元素是无符号长。请注意,如果我明确地将vpc转换为(RenFlexibleVertexPc *

,则代码在GCC中有效

如果它是枚举为什么要传递struct类型数组4的对象?什么是RenFlexibleVertexPcdrawVertices的最后一个参数应该是指向Vertex对象的常量指针,或const*指向从Vertex派生的类的对象。

Foo *renderer;
renderer->drawVertices(4, RenPrimTriangleFan, material, vpc);

您正在调用未初始化指针上的函数。我希望这不是真正的代码。 \