6

我有以下代码:

它在 gcc-3.4、gcc-4.3、intel 编译器下编译没有问题,但在 MSVC9 下编译失败。

MSVC 告诉“使用未定义类型,同时使用 C=shortc_traits<C>编译类模板成员函数。void foo<C>::go(void)

编译器试图安装未使用类的未使用成员函数,因为这个类根本没有使用。

我可以通过专门化整个类 foo 而不是专门化其成员函数来解决这个问题。但是,由于不同的原因,专业化整个班级对我来说有点问题。

最大的问题:什么是对的?

  • 我的代码是否错误并且 gcc 和 intel 编译器只是忽略了这个问题,因为它们没有完全安装 foo,或者
  • 代码是正确的,这是 MSVC9 (VC 2008) 的错误,它试图安装未使用的成员函数?

编码:

class base_foo {
public:
    virtual void go() {};
    virtual ~base_foo() {}
};
template<typename C>
struct c_traits;

template<>
struct c_traits<int> {
    typedef unsigned int_type;
};

template<typename C>
class foo : public base_foo {
public:
    static base_foo *create()
    {
        return new foo<C>();
    }
    virtual void go() 
    {
        typedef typename c_traits<C>::int_type int_type;
        int_type i;
        i=1;
    }
};

template<>
base_foo *foo<short>::create()
{
    return new base_foo();
}

int main()
{
    base_foo *a;
    a=foo<short>::create(); delete a;
    a=foo<int>::create(); delete a;
}
4

2 回答 2

3

两个编译器都在这里;您的案例的行为未指定。ISO C++ 14.7.1[temp.inst]/9:

实现不应隐式实例化不需要实例化的类模板的函数模板、成员模板、非虚拟成员函数、成员类或静态数据成员。如果虚拟成员函数不会被实例化,则未指定实现是否隐式实例化类模板的虚拟成员函数。

The reasoning for this is fairly simple: a virtual function requires a vtable entry, and with virtual dispatch, it may be tricky for the compiler to determine whether a given virtual function is actually called or not. Therefore, ISO C++ permits the compilers to do such advanced analysis for the sake of generating smaller code, but does not require it of them - so, as a C++ programmer, you should always assume that all virtual functions will always be instantiated.

于 2009-11-02T19:41:56.800 回答
1

未使用的函数的删除将发生在链接而不是在您遇到错误的编译时。MSVC 可能不知道在所有正在编译的编译单元中谁最终会调用该方法。在编译完成和链接发生之​​前,它无法知道。自然不同的编译器可能对此更聪明,但我怀疑这可能是正在发生的事情。

我怀疑您的特定编译器错误听起来像是由您仅向前声明引起的

template<typename C>
struct c_traits;

你还没有完全指定类。您是否尝试过以下简单的方法:

template<typename C>
struct c_traits 
{
    // some default/dummy int type
};

我怀疑这至少会阻止编译器抱怨。

编辑

这对于类模板通常是错误的。类模板的成员函数不应该被编译(并且它们的主体中的任何错误都不应该被触发),除非它们被实例化

在这种情况下,模板以以下形式实例化:

 foo<short>

编译器会将其视为具有外部链接潜力的任何其他类。我没有听到任何特殊的语言规则说外部链接不适用于模板......?

于 2009-11-02T18:43:15.867 回答