首页 > 解决方案 > 为什么 SFINAE 在这个简单的成员函数重载中不起作用

问题描述

为什么 SFINAE 在这个简单的例子中不起作用?如果我注释掉模板化的“添加”,则代码编译正常。为什么编译器在替换失败后不尝试调用非模板'add'?

我正在使用 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 等)的情况下使该代码工作?

标签: c++c++14

解决方案


cppreference

只有函数类型或其模板参数类型 [或其显式说明符 (C++20 起)] 的直接上下文中的类型和表达式中的失败是 SFINAE 错误

在这里,失败发生在函数体中,所以它是替换失败,但不是在 SFINAE 上下文中 - 所以这是一个错误。

概念旨在帮助减少样板文件的繁重,因此如果您的编译器已经支持它们,您可以尝试使用它们。


推荐阅读