VC 2013: использование-declaration переопределение функции-члена приводит к ошибке компиляции

#c #visual-c -2013

#c #visual-c -2013

Вопрос:

Я хочу разрешить изменять поведение моего класса, указав политику. Эта политика должна использоваться в качестве посетителя для boost::variant . Существует политика по умолчанию, которая подходит для большинства случаев, но пользователю может потребоваться добавить или заменить некоторые перегрузки.

Я обнаружил, что vc 2013 не компилирует этот код с ошибкой C3066: there are multiple ways that an object of this type can be called with these arguments . Тот же код компилируется и работает, как и ожидалось, в gcc и clang.

Это ошибка vc 2013?

 #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 Этот пример работает в vc 2010. Похоже, это ошибка в версии 2013.


UPD обходной путь

 #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 amp;amp; 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;
}
  

Комментарии:

1. Какой вызов генерирует ошибку?

2. Какая версия vc ?

3. UserModifiedPolicy()(1); // ошибка здесь (перегрузка int)

Ответ №1:

Код хорошо сформирован. 7.3.3/15:

Когда using-declaration переносит имена из базового класса в область производного класса, функции-члены и шаблоны функций-членов в производном классе переопределяют и / или скрывают функции-члены и шаблоны функций-членов с тем же именем, списком типов параметров (8.3.5), cv-qualification и ref-qualifier(если есть) в базовом классе (а не конфликтующем).

Поэтому UserModifiedPolicy::operator()(int) все равно следует скрывать DefaultPolicy::operator()(int) . И поиск имени для operator() должен найти три члена DefaultPolicy::operator()(bool) , UserModifiedPolicy::operator()(int) , и UserModifiedPolicy::operator()(float) .