VC++ 2013: using-declaration + redefinition of member function leads to compile error
Asked Answered
C

1

4

I want to allow to modify behaviour of my class by specifing policy. This policy shoud be used as visitor for boost::variant. There is default policy that fits most cases good, but user may need to add or replace some overloads.

I found that vc++ 2013 doesn't compile this code with error C3066: there are multiple ways that an object of this type can be called with these arguments. Same code compiles and works as expected in gcc and clang.

Is it vc++ 2013 bug?

#include <iostream>

struct DefaultPolicy
{
    void operator()( bool ) { std::cout << "Base: bool" << std::endl; }
    void operator()( int ) { std::cout << "Base: int" << std::endl; }
};

struct UserModifiedPolicy : public DefaultPolicy
{
    using DefaultPolicy::operator();
    void operator()( int ) { std::cout << "Derived: int" << std::endl; }
    void operator()( float ) { std::cout << "Derived: float" << std::endl; }
};

int main()
{
    UserModifiedPolicy()(true);
    UserModifiedPolicy()(1); // <-- ERROR HERE
    UserModifiedPolicy()(1.f);
    return 0;
}

UPD This exaple works in vc++ 2010. Looks like it is a bug in 2013 version.


UPD Workaround

#include <iostream>

struct DefaultPolicy
{
    void operator()( bool ) { std::cout << "Base: bool" << std::endl; }
    void operator()( int ) { std::cout << "Base: int" << std::endl; }
};

struct UserModifiedPolicy : public DefaultPolicy
{
    // Using template to forward a call to the base class:
    template< class T >
    void operator()( T && t ) { DefaultPolicy::operator()( std::forward<T>(t) ); }

    void operator()( int ) { std::cout << "Derived: int" << std::endl; }
    void operator()( float ) { std::cout << "Derived: float" << std::endl; }
};

int main()
{
    UserModifiedPolicy()(true);
    UserModifiedPolicy()(1);
    UserModifiedPolicy()(1.f);
    return 0;
}
Concertize answered 25/6, 2014 at 12:56 Comment(3)
Which call generates the error?Kayser
What version of vc++ ?Vivisectionist
UserModifiedPolicy()(1); // error here (int overload)Concertize
W
2

The code is well-formed. 7.3.3/15:

When a using-declaration brings names from a base class into a derived class scope, member functions and member function templates in the derived class override and/or hide member functions and member function templates with the same name, parameter-type-list (8.3.5), cv-qualification, and ref-qualifier (if any) in a base class (rather than conflicting).

So UserModifiedPolicy::operator()(int) should still hide DefaultPolicy::operator()(int). And name lookup for operator() should find the three members DefaultPolicy::operator()(bool), UserModifiedPolicy::operator()(int), and UserModifiedPolicy::operator()(float).

Williemaewillies answered 25/6, 2014 at 13:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.