【发布时间】:2020-09-19 18:35:04
【问题描述】:
假设类型可以有Foo、Bar、Baz 方法,我们有类型特征来检查它。例如。对于Foo,我们有HasFoo:
template <class Type>
constexpr bool DetectFoo (decltype (std::declval<Type> ().Foo ())*) { return true; }
template <class Type>
constexpr bool DetectFoo (...) { return false; }
template <class Type>
constexpr bool HasFoo = DetectFoo<Type> (nullptr);
让我们编写一个Wrapper<Type> 类模板,它转发Type 的属性是否具有这些方法。对于任何Type,应满足以下条件:
-
Wrapper<Type> w;应该可以编译,因为我们还没有调用方法。 -
w.X ();应该编译 iffHasX<Type>, 对于X=Foo,Bar,Baz。 -
HasX<Wrapper<Type>> == HasX<Type>应该成立,因为X=Foo,Bar,Baz。
要在Wrapper 中有条件地启用一个方法,在 C++20 中有一个明确的方法:
template <class Type>
struct Wrapper {
void Foo ()
requires HasFoo<Type>;
};
但是在没有概念的情况下,在早期的 C++ 标准中该怎么办?我想出了以下想法(见live demo):
template <class Type>
struct Wrapper {
template <bool dummy = true, class = std::enable_if_t<HasFoo<Type> && dummy>>
void Foo ();
};
This answer 说它格式错误,NDR,但我不明白解释。 NDR 真的格式不正确吗?
【问题讨论】:
-
class = std::enable_if_t<HasFoo<Type> && dummy>这应该做什么/意味着什么?我真的无法理解它,它显然不是格式正确的代码。 -
也许你被否决的原因之一是你的问题有点令人困惑。有更多的解释,然后是显示你想要的代码。您对
FooBar和Baz和HasX的描述很容易被误解。只需显示您想要的代码。代码比代码解释更容易理解。 -
我还有更多问题。假设我们有一个带有方法
Foo和Bar但没有Baz的类型。然后我们已经可以在上面调用Foo()和Bar(),但是Baz()会因为编译时错误而失败。那么Wrapper究竟应该做什么或在那里做什么?您可以从传入的类继承,您将自动获得该行为。这有助于使这个问题更不清楚您真正想要实现的目标。 -
@super:我已经编辑了这个问题。希望现在更好。
Wrapper<Type>不能继承Type的形式,因为Type可能是final甚至不是一个类。例如,Wrapper<Type>可以选择包含Type,而Foo、Bar、Baz可以是比较运算符,它们应该存在于Wrapper<Type>上,前提是它们存在于Type上。
标签: c++ templates c++17 instantiation sfinae