C++ 在使用“std::enable_if”时,如何避免写入“::value”和“::type”?[cppx]
注意:这是一个,目的是记录其他人可能会发现有用的技术,并了解其他人更好的解决方案。请随意添加评论或问题作为评论。也可以随意添加其他答案。:)C++ 在使用“std::enable_if”时,如何避免写入“::value”和“::type”?[cppx],c++,templates,c++11,C++,Templates,C++11,注意:这是一个,目的是记录其他人可能会发现有用的技术,并了解其他人更好的解决方案。请随意添加评论或问题作为评论。也可以随意添加其他答案。:) 在我的一些代码中,即标题rfc/cppx/text/String.h,我发现了以下神秘片段: template< class S, class enable = CPPX_IF_( Is_a_< String, S > ) > void operator! ( S const& ) { string_detail::Me
在我的一些代码中,即标题
rfc/cppx/text/String.h
,我发现了以下神秘片段:
template< class S, class enable = CPPX_IF_( Is_a_< String, S > ) >
void operator! ( S const& )
{ string_detail::Meaningless::operation(); }
这看起来像是std::enable_if
template< class S, class enabled = typename std::enable_if< Is_a_< String, S >::value, void >::type >
void operator! ( S const& )
{ string_detail::Meaningless::operation(); }
template::value,void>::type>
无效操作员!(S常数&)
{string_detail::无意义::operation();}
除了If
或CPPX\u If
及其表达式更简洁易读之外
我到底是怎么做到的?使用编译器的舒适的C++11-
功能就是
namespace cppx {
using std::enable_if;
template< class Condition_type, class Result_type = void >
using If_ = typename enable_if<Condition_type::value, Result_type>::type;
} // namespace cppx
这基本上只提供了一个更可读的名称,并且在条件中省去了::value
。为了省去typename
和::type
我使用了一个宏。但由于表达式通常是模板表达式,因此预处理器可能会将逗号解释为参数分隔符,以便预处理器可以看到多个参数
namespace cppx {
using std::integral_constant;
template< bool c >
using Bool_ = integral_constant<bool, c>;
using False = Bool_<false>; // std::false_type;
using True = Bool_<true>; // std::true_type;
template< bool v, class First, class... Rest >
struct Count_
{
enum{ value = Count_<v, First>::value + Count_<v, Rest...>::value };
};
template< bool v, class X >
struct Count_<v, X>
{
enum{ value = int(!!X::value == v) };
};
template< class X >
using Not_ = Bool_<Count_<true, X>::value == 0>; // NOT
template< class... Args >
using All_ = Bool_<Count_<false, Args...>::value == 0>; // AND
template< class... Args >
using Some_ = Bool_<Count_<true, Args...>::value != 0>; // General inclusive OR.
template< class... Args >
using Either_ = Bool_<Count_<true, Args...>::value == 1>; // General exclusive OR.
} // namespace cppx
我使用的解决方案(C++03的时代对我来说已经结束)是使用C99/C++11可变宏
#define CPPX_IF_( ... ) \
typename cppx::If_T_< __VA_ARGS__ >::T
此外,为了完整性,是一个
被简单地定义为
template< class Base, class Derived_or_eq >
using Is_a_ = std::is_base_of<Base, Derived_or_eq>;
免责声明:没有一个代码被广泛测试,C++模板编译器在模板元编程领域的奇特是常见的。
< P> C++ 14中,变量模板使类型特征更容易观察。再加上C++11模板别名,所有的污点都会消失:
template <typename A, typename B>
bool is_base_of_v = std::is_base_of<A, B>::value;
template <bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;
模板
bool是v=std::的基础值::value的基础值;
模板
使用enable_if_t=typename std::enable_if::type;
用法:
template <typename B, typename D>
enable_if_t<is_base_of_v<B, D>, Foo> some_function(B & b, D & d) { /* ... */ }
模板
启用某些函数(B&B,D&D){/*…*/}
“Type”形式的别名实际上是C++14标准库的一部分,请参见[meta.Type.synop]。我们有C++03、C++11和C++14解决方案,但缺少:
template <typename Derived, typename Base>
constexpr bool Is_a_() {
return std::is_base_of<Base, Derived>::value;
}
template<Is_a_<String> S>
void operator! ( S const& )
{ string_detail::Meaningless::operation(); }
模板
constexpr bool是{
return std::是::value的_base_;
}
模板
无效操作员!(S常数&)
{string_detail::无意义::operation();}
或者更简洁地说:
template <typename Derived, typename Base>
concept bool Is_a_() {
return std::is_base_of<Base, Derived>::value;
}
void operator! ( Is_a_<String> const& )
{ string_detail::Meaningless::operation(); }
模板
概念布尔是{
return std::是::value的_base_;
}
无效操作员!(是常数&)
{string_detail::无意义::operation();}
我强烈建议浏览本文的教程(第2节),了解一下在我们摆脱了enable\u if
霸主之后,世界会变得多么美好。像std::enable\u if\u t
这样的新模板别名是C++14的一部分,我相信。@KerrekSB,酷,我不知道他们真的实施了这些。你知道他们有没有为::value
做过任何\u v
变量模板或其他什么吗?@KerrekSB:谢谢!我不知道。它省去了typename
和::type
字眼,但没有::value
。总之,Visual C++还没有支持。可能不会很长时间……取消::value
需要可变模板。这些也是C++14的一部分,但我不知道是否计划了相应的新特性。看起来不像,尽管那是一种耻辱代码>,等等。如模板bool是\u base\u of of v=std::is\u base\u of::value
。你可以用C++14编写。这比你的特殊条件评估包装更干净。很高兴知道,谢谢!但是,在软膏中,一个在Windows中实际上无法使用它,直到VisualC++支持它…@ TeMtPrimeX:是的,C++和111模板别名都用于MIGER和Kerrek的答案,但是,不,VC 12支持不完整,也不完全是无bug的。对于即将到来的C++ 14“变量模板”,上面的代码没有用Visual C++ 12(2013)编译。它也不是用g++4.8.2编译的。因此,我认为这与我对So(一个大约有50%的类似Herb Schildt的虚假信息的网站,可能是网络上最大的此类信息)的看法是一致的,你的评论被两位读者投了更高的票。C++14信息+1(在你发布这篇文章时是正确的)。然而,它只是事物的形状。@ TePrimeRe: RE“你能给出一个小例子,这个特性在VC++上不起作用”,如上面提到的两次(这个答案)是一个不工作的例子,不支持,如VisualC++ 2013。但是我不能预测未来,抱歉。啊,我刚刚检查过,N3797确实指定了一个std::enable\u if\t
。我将提交一个DR.Concepts Lite,它还具有闪亮和新颖的优点,因此微软可能会在修复C++98错误之前在他们的编译器中实现它。
template <typename B, typename D>
enable_if_t<is_base_of_v<B, D>, Foo> some_function(B & b, D & d) { /* ... */ }
template <typename Derived, typename Base>
constexpr bool Is_a_() {
return std::is_base_of<Base, Derived>::value;
}
template<Is_a_<String> S>
void operator! ( S const& )
{ string_detail::Meaningless::operation(); }
template <typename Derived, typename Base>
concept bool Is_a_() {
return std::is_base_of<Base, Derived>::value;
}
void operator! ( Is_a_<String> const& )
{ string_detail::Meaningless::operation(); }