c++ - Ideone 中的 SFINAE 问题?

标签 c++ c++11

我正在尝试通过比较 Visual Studio 的输出与 GCC 的输出来调试我在 Visual Studio 中遇到的问题,但我似乎无法获得要在 Ideone 中编译的极其简化的代码版本:

#include <exception>
#include <iostream>

template <int x>
struct foo {};

template <>
struct foo<0> { using type = int; };

template <typename Foo>
struct bar
{
    bar(void) {}

    template <typename = typename Foo::type>
    bar(const bar &) {}
};

int main(void)
{
    bar<foo<1>> x;
}

当我尝试使用 Ideone 运行它时,上面给出了错误:

prog.cpp: In instantiation of ‘struct bar<foo<1> >’:
prog.cpp:21:17:   required from here
prog.cpp:16:5: error: no type named ‘type’ in ‘struct foo<1>’
     bar(const bar &) {}

根据我的理解,替换Foo::type 失败不应导致编译错误。请注意,使复制构造函数 bar(const bar &) { typename Foo::type x; } 允许程序编译得很好。我试图以与使用 std::enable_if 几乎完全相同的方式使用此模板,这在类中的任何地方使用时也会导致编译错误——而不仅仅是在复制构造函数上。这是正确的行为吗?我很确定不是,但我一直认为 Ideone 在后端使用 GCC...

最佳答案

是的,这种行为是正确的。

SFINAE 适用于在函数模板重载解析期间推导模板参数(允许编译器丢弃特化而不发出错误)。

在您的情况下,错误不是在重载解析期间发生的,而是在模板实例化期间发生的:bar模板根本无法实例化,因为复制构造函数需要嵌套类型 Foo::type 的存在, 当模板参数为 foo<1> 时不存在.

最后一点,如果你声明:

template <typename Foo>
struct bar
{
    bar(void) {}

    bar(const bar &) { typename Foo::type x; }
};

只要您不调用复制构造函数,它就可以正常编译。 使用复制构造函数会导致同样的编译错误:

bar<foo<1>> x2 = x; // Error

关于c++ - Ideone 中的 SFINAE 问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26111044/

相关文章:

c++ - Visual Studio 2017 发布版本中的 Eigen cwisemin/cwisemax 访问冲突

c++ - 运行我的程序说 "bash: ./program Permission denied"

c++ - 从类中删除列表元素

C++ 用另一个 vector 扩展一个 vector

c++ - 尝试将参数包的第一个元素作为函数调用并将包的其余部分作为参数传递给它

c++ - 决定返回什么 - boolean 值

C++ 如何绑定(bind)和调用模板化类型方法

c++ - 如何理解*(void **)(&m_handle)= dlsym (“./haldle_lib.so”, “custom_func”);

c++ - 自动释放由外部 api 分配的对象

c++ - 关于创建 boost.asio async_xxxx 处理程序对象