我正在尝试通过比较 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/