使用 C++11 中的
CRTP
习惯用法,我试图检查派生类是否具有名为 size
的方法。
#include <iostream>
template<typename Derive> struct IsContainer {
template<typename Der> static constexpr bool has_size( decltype(&Der::size) ) { return true; }
template<typename Der> static constexpr bool has_size(...) { return false; }
static constexpr bool value = has_size<Derive>(nullptr);
};
struct Container : IsContainer<Container> {
const unsigned int size();
};
struct NonContainer : IsContainer<NonContainer> {};
int main() {
Container obj;
std::cout << obj.value <<std::endl;
}
然后我尝试摆脱
template <typename Der>
,如下所示:
#include <iostream>
template<typename Derive> struct IsContainer {
static constexpr bool has_size( decltype(&Derive::size) ) { return true; }
static constexpr bool has_size(...) { return false; }
static constexpr bool value = has_size(nullptr);
};
struct Container : IsContainer<Container> {
const unsigned int size();
};
struct NonContainer : IsContainer<NonContainer> {};
int main() {
Container obj;
std::cout << obj.value <<std::endl;
}
编译错误:
In instantiation of ‘struct IsContainer<Container>’:
error: incomplete type ‘Container’ used in nested name specifier
| static constexpr bool has_size( decltype(&Derive::size) ) { return true; }
| ^~~~~~~~
我遇到了这样一个引用自标准的语句,解释了为什么编译器会给出这个错误
3.3.2p6 声明点 [basic.scope.pdecl]
一旦声明了类成员,就可以在类范围内搜索其名称
我仍然不明白为什么第一个代码片段有效而第二个代码片段无效。如果有人向我详细解释并可能给我一个提示来解决第二个代码片段的错误,我真的很感激。
通过删除 template-head
template <typename Der>
,这些成员就不可能有 SFINAE,因此我们会得到一个 硬错误。 SFINAE 在模板参数替换期间发生,并且没有 template-head 就没有替换,也没有 SFINAE。