6

下面是重新创建我遇到的问题的代码。Baseclass 是一个带有虚函数的模板类foofoo具有添加传入参数的默认实现。

SimpleDerived源自Base,专门用于std::stringSimpleDerived重载虚Base<T>::foo()函数。此类foo在调用时可以正常编译,并且其输出符合预期main

#include <iostream>

template<class T>
struct Base
{
    virtual void foo(T val)
    {
        T local = val + val;    // THE OFFENDING LINE OF CODE
        std::cout << "Base" << std::endl;
    }   
};

struct SimpleDerived : public Base<std::string>
{
    virtual void foo(std::string val)
    {
        std::cout << "SimpleDerived" << std::endl;
    }
};

struct SimpleObject
{
    int value;
};

struct ComplexDerived : public Base<SimpleObject>
{
    virtual void foo(SimpleObject val)
    {
        std::cout << "ComplexDerived" << std::endl;
    }   
};

int main(void)
{
    Base<int> base;
    base.foo(2);

    SimpleDerived simpleDerived;
    simpleDerived.foo("hello world");

    SimpleObject object;
    ComplexDerived complexDerived;
    complexDerived.foo(object);

    return 0;
}

ComplexDerived派生自Base,使用自定义结构对其进行专门化SimpleObjectComplexDerived过载foo也是如此。然而,这是问题的根源。如果我尝试编译它,我会得到:

quicktest.cpp: In member function ‘void Base<T>::foo(T) [with T = SimpleObject]’:
quicktest.cpp:47:1:   instantiated from here
quicktest.cpp:8:19: error: no match for ‘operator+’ in ‘val + val’

显然,没有运算符“+” SimpleObject。但这是我的困惑..编译器被要求实现Base<SimpleObject>::foo,因为这是ComplexDerived继承的。但是,我从不使用或调用Base<SimpleObject>::foo. 那么编译器是否应该尝试生成这个基类函数?

4

1 回答 1

10

C++11 标准的第 14.7.1/10 段规定:

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

换句话说,这种情况下的行为是特定于实现的。

虽然理论上编译器可以确定永远不会调用对基类实现的foo()调用(因为函数调用不是通过引用或指针发生)并避免实例化它,但标准并未强制执行此行为.

于 2013-06-14T23:38:13.173 回答