如何解决在C ++ 17中有条件启用的成员函数
假设类型可以有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 ();
应该在HasX<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吗?
解决方法
您的代码格式正确。
链接的答案指向[temp.res.general]/8.1
:
可以在任何实例化之前检查模板的有效性。 ...该程序格式错误,如果出现以下情况,则无需进行诊断:
-无法为模板生成有效的专业化...并且该模板未实例化,...
在这里,我们正在谈论的“模板”是Foo
。
我相信这可以用两种方式解释:
(1)我们可以认为Wrapper<A>::Foo
和Wrapper<B>::Foo
是相同的模板(对于每个A
,B
)。然后,仅存在Wrapper
这样的模板参数,使得enable_if_t
true
中的条件足以使代码格式正确。
(2)我们也可以将Wrapper<A>::Foo
和Wrapper<B>::Foo
视为不同模板(对于A != B
)。然后,如果存在Wrapper
的模板参数,而无法实例化Foo
,则您的代码将是格式错误的NDR。但这永远不会发生,因为您总是可以将HasFoo
专门化为每个模板参数的true
!
无论如何,我认为(1)是预期的解释。 [temp.res.general]/8.1
的目的不是妨碍您,而是通过尽可能早地验证模板来帮助您。我从未见过编译器使用第二种解释。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。