Below is the code to recreate the problem I am having. Base
class is a template class with the virtual function foo
. foo
has a default implementation that adds the passed in arguments.
SimpleDerived
derives from Base
, specializing it with std::string
. SimpleDerived
overloads the virtual Base<T>::foo()
function. This class compiles fine and its foo
outputs as expected when called in 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
derives from Base
, specializing it with a custom struct SimpleObject
. ComplexDerived
overloads foo
as well. However, this is the root of the problem. If I try to compile this I get:
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’
Obviously, there is no operator "+" for SimpleObject
. But here is my confusion.. the compiler is being asked to implement Base<SimpleObject>::foo
because this is what ComplexDerived
inherits from. However, I never use or call Base<SimpleObject>::foo
. So should the compiler be trying to generate this base class function?
Paragraph 14.7.1/10 of the C++11 Standard specifies:
An implementation shall not implicitly instantiate a function template, a member template, a non-virtual member function, a member class, or a static data member of a class template that does not require instantiation. It is unspecified whether or not an implementation implicitly instantiates a virtual member function of a class template if the virtual member function would not otherwise be instantiated. [...]
In other words, the behavior in this case is implementation-specific.
While in theory the compiler could figure out that the call to the base class's implementation of foo()
won't ever be invoked (since the function call does not occur through a reference or pointer) and avoid instantiating it, this behavior is not mandated by the Standard.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With