Why does C++ prefer this template method to a method overload?

boost, c++, overloading, templates

Solution

The problem is that at the point you're calling `writer.Write(x)` the compiler sees a `ComplexWriter` not a `ComplexWriterImpl`, so it is only aware of the functions defined in `ComplexWriter` - the template function and the `boost::any` function.

`ComplexWriter` does not contain any virtual functions that accept an `int`, so it has no way to call through to the int overload defined in `ComplexWriterImpl`

When you add in the virtual overload to the `ComplexWriter` class, then the compiler becomes aware that there is an integer overload in the `ComplexWriter` class and therefore calls through to it's implementation in `ComplexWriterImpl`

EDIT: Now that you've edited in the inheritance between ComplexWriter & Writer, I've got a more complete explanation for you:

When you create a subclass and define a function in it then all of the functions of that name in the base class will be hidden, regardless of their argument types.

You can get around this with the using keyword I believe:

struct ComplexWriter : public Writer {
    template <typename TValue> void Write(const TValue &value) {
        boost::any any(value);
        Write(any);
    }
    using Writer::Write;
    virtual void Write(const boost::any &any) = 0;
};

For more details see this FAQ entry: http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9

EDIT 2: Just to confirm that this does indeed solve your problem: http://ideone.com/LRb5a

Problem

Assuming I had two classes, the first one for writing primitive types (`bool`, `int`, `float`, etc.) and the second one extending the first to also write complex types: ``` struct Writer { virtual void Write(int value) = 0; }; struct ComplexWriter : public Writer { template <typename TValue> void Write(const TValue &value) { boost::any any(value); Write(any); } //virtual void Write(int value) = 0; // see question below virtual void Write(const boost::any &any) = 0; }; ``` The idea is that if someone calls `myWriter.Write(someIntValue);`, the int overload will receive priority over the templated method. Instead, my compiler (Visual C++ 11.0 RC) always picks the template method. The following code snippet, for example, will print `Wrote any` to the console: ``` struct ComplexWriterImpl : public ComplexWriter { virtual void Write(int value) { std::cout << "Wrote an int"; } virtual void Write(const boost::any &any) { std::cout << "Wrote any"; } }; void TestWriter(ComplexWriter &writer) { int x = 0; writer.Write(x); } int main() { ComplexWriterImpl writer; TestWriter(writer); } ``` The behavior suddenly changes when I declare the `Write(int)` method in the `ComplexWriter` class as well (see commented out line in the first snippet). It then prints `Wrote an int` to the console. Is this how my compiler ought to behave? Does the C++ standard explicitly say that only overloads defined in the same class (and not a base class) shall be prioritized over a templated method?

Original source