Почему SFINAE не работает в этой простой функции перегрузки - PullRequest
0 голосов
/ 14 июня 2019

Почему SFINAE не работает в этом простом примере?Если я закомментирую шаблон «добавить», код компилируется нормально.Почему компилятор не пытается вызвать не-шаблон «добавить» после ошибки замещения?

Я использую MSVS 2017.


#include <set>
#include <memory>

struct button_t
{
    virtual ~button_t() {}
};

struct up_down_button_t : button_t
{
};


struct gui_t
{

    std::set<std::shared_ptr<button_t> > buttons;

    void add(const std::shared_ptr<button_t>& b) {
        buttons.insert(b);
    }

    template<class container_t>
    void add(container_t& c) {
        for (auto& i : c)
            add(i);
    }

} gui;

int main(int argc, char* argv[]) {


    auto b = std::make_shared<up_down_button_t>();
    gui.add(b);

}

Можно ли заставить этот код работать безподробный шаблонный код, такой как std :: enable_if и т. д.

Ответы [ 2 ]

1 голос
/ 14 июня 2019

Если вы измените свою первую функцию на:

template <class ptr_t>
void add(std::shared_ptr<ptr_t>& b) {
    buttons.insert(b);
}

Тогда ваш код скомпилируется и будет работать как положено.

Обратите внимание на две вещи:

  • Обе функции template.
  • Оба принимают ссылку на не const объект.

Допустимая функция шаблона предпочтительнее, чем не шаблонная функция, которая нуждается в некотором «преобразовании».

Кстати, в вашем примере нет СФИНАЕ. Фактически, template<class container_t> void add(container_t& c) является приемлемым совпадением.

1 голос
/ 14 июня 2019

От cppreference :

Только ошибки в типах и выражениях в непосредственном контексте типа функции или ее типов параметров шаблона [или ее явного спецификатора (начиная с C ++ 20)] являются ошибками SFINAE

Здесь сбой происходит в теле функции, поэтому это сбой замещения, но не в контексте SFINAE - поэтому это ошибка.

Концепции призваны помочь сделать этот шаблон менее тяжелым, поэтому вы можете попробовать использовать их, если ваш компилятор уже поддерживает их.

...