2016-05-16 3 views
4

Я не понимаю, почему компилятор выбирает конструктор копирования моего класса Production и не имеет других функций-кандидатов. я сделал минимальный пример, чтобы продемонстрировать ошибку:Конструктор шаблонов Variadic и конструктор копирования

#include <string> 
#include <typeindex> 
#include <iostream> 

struct DummyProduction { 
}; 

struct Dep { 
}; 

struct Pro { 
}; 

class ModuleBase { 
}; 

template<typename Production = DummyProduction> 
class Provider { 
public: 
    template<typename... Dependencies> 
    Provider(ModuleBase& module, Dependencies... args) 
    { 
    std::cout << "Provider called!" << std::endl; 
    } 
    Provider(const Provider&) = delete; 
}; 

class TargetController : public ModuleBase, 
    public Provider<Pro>, 
    public Provider<> 
{ 
public: 
    TargetController(); 
private: 
    Dep p; 
}; 

TargetController::TargetController() : 
    ModuleBase(), 
    Provider<Pro>(*this, &p), 
    Provider<>(*this), 
    p() 
{ 
} 

int main() 
{ 
    TargetController x; 
    return 0; 
} 

Я попробовал его с GCC и лязгом. Вот ссылка на нерабочий пример: link.

Для Provider<Pro>(*this, p) вызывается правый конструктор. Но для второго примера Provider<>(*this) компилятор пытается вызвать экземпляр-конструктор.

Из того, что я понял с страницы Overload resolution, все функции, соответствующие выражениям, должны попадать внутрь набора функций-кандидатов. Но либо переменный constuctor не находится внутри набора для провайдера без зависимостей, либо компилятор выбирает конструктор-копию, несмотря на удаление.

Есть ли способ избежать такого поведения?

+0

Такой вопрос заставляет меня смириться :). +1 для него – Makketronix

+1

[OT]: Обратите внимание, что 'p' еще не построено в вызове' Provider (* this, p) '. – Jarod42

+0

@ Jarod42 Да, это правильно, я забыл, что, уменьшая код до минимального примера. – Nagua

ответ

2

Тот факт, что функция/метод deleted не удаляет его из списка перегрузки. И конструктор копирования имеет более высокий приоритет над методом шаблона (поскольку он не является точным соответствием).

Как временное решение вы можете закинуть к ожидаемому типу:

TargetController::TargetController() : 
    ModuleBase(), 
    Provider<Pro>(*this, p), 
    Provider<>(static_cast<ModuleBase&>(*this)) 
{ 
} 

Demo

+0

Хорошо, слишком плохо, что нет возможности удалить экземпляр-конструктор из списка перегрузки. Да, это работает в моем коде. Итак, подумайте, что я должен использовать это сейчас. Спасибо. – Nagua

0

Шаблонные конструкторы никогда не копировать конструкторы. Когда вы вызываете конструктор базы и передаете ему ссылку на базу (или на производную), предполагается, что будет создан конструктор копирования. В этом контексте шаблон не является вариантом.

Provider<>(*this) 

Это такой контекст.

Стоит отметить, что я считаю, что ВС все еще не так. В этом компиляторе вы должны наложить на базу & или он будет вызывать шаблон.

+0

Спасибо за объяснение, почему это не работает. У вас есть ссылка на стандарт C++, что нет другого конструктора, который можно использовать? – Nagua

Смежные вопросы