【发布时间】:2018-10-14 05:00:12
【问题描述】:
我的目标是实现一个谓词来检测嵌套的using 别名(或typedef)的存在,该别名充当轻量级标签以指示类具有某些属性(出于通用编程的目的)。例如,has_my_tag<T> 谓词的行为如下:
struct A {
using my_tag = void;
};
struct B {};
int main()
{
static_assert(has_my_tag<A>::value, ""); // evaluate to true if my_tag=void is present
static_assert(!has_my_tag<B>::value, ""); // false otherwise
}
用户@JoelFalcou 将此称为“轻量级类型分类习语”,并在this answer 中提供了解决方案。我一直找不到该名称的成语的任何参考资料(你知道吗?)这是乔尔对has_my_tag<> 的实现:
template<class T, class R = void>
struct enable_if_type { typedef R type; };
template<class T, class Enable = void>
struct has_my_tag : std::false_type {};
template<class T>
struct has_my_tag<T, typename enable_if_type<typename T::my_tag>::type> :
std::true_type
{};
这是编译器资源管理器上的工作版本:https://godbolt.org/z/EEOBb-
我想出了以下简化版:
template<class T, class Enable = void>
struct has_my_tag : std::false_type {};
template<class T>
struct has_my_tag<T, typename T::my_tag> : std::true_type
{};
我的问题:简化版本是否是一种可接受的方式来实现这个成语?有没有会失败的情况?有在 C++11 中工作的更简单的版本吗?我应该更喜欢哪个版本?
据我了解,Joel 的版本将允许 my_tag 为任何类型起别名,而我的版本要求 my_tag 为 void 起别名。但是考虑到为轻量级谓词测试标记类型的目标,我不清楚哪个版本是首选。
辅助问题:另外,这个成语还有其他名称吗?它是否用于我可以调查的任何库中?到目前为止,我还没有找到可以显示任何搜索结果的名称。
【问题讨论】:
-
“简化版本是否是一种可接受的方式来实现成语”显然完全取决于它是否正常工作。那是你自己做的决定。它是否正常工作,是否符合您的预期目的。这是您可以简单地为其编写测试用例的东西,如果最终结果是正确的,那么它是“实现这个习语的一种可接受的方式”。你不应该期望任何人告诉你“[你]更喜欢哪个版本”。你可以自己做出决定。最后,至于是否有“其他名称”:不幸的是,我不玩流行语宾果游戏。
-
@SamVarshavchik 使用习语的目的是保持一致并熟悉读者的期望。您的建议似乎表明,只要通过测试,晦涩、陌生和单一的代码是完全可以接受的。我不同意。
-
为什么要使用最简单的相关性实现?将实现细节放在内部命名空间中,
has_my_tag的用户将永远不必关心它...... -
您的版本需要更改名称,因为您还要求
my_tag是void。 -
我称之为检测成语(即使有几种不同的实现(如std::experimental::is_detected))