Che*_*Alf 16 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::Meaningless::operation(); }
Run Code Online (Sandbox Code Playgroud)
它operator!支持String一个隐式转换为原始指针的类.所以我operator!为这个类和派生类重载(以及其他),因此无意中使用不受支持的运算符会给出一个合适的编译错误,提到它没有意义且无法访问.我认为这种使用方式比使用意外的错误结果而被默默接受更为可取.
该CPPX_IF_宏支持Visual C++ 12.0(2013)及更早版本,它发现C++ 11 using大部分都超出了它的范围.对于更符合标准的编译器,我只会写...
template< class S, class enable = If_< Is_a_< String, S > > >
void operator! ( S const& )
{ string_detail::Meaningless::operation(); }
Run Code Online (Sandbox Code Playgroud)
看起来像 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(); }
Run Code Online (Sandbox Code Playgroud)
除了If_or CPPX_IF_和它的表达,它更简洁和可读.
我是怎么做到的?
Ker*_* SB 28
在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;
Run Code Online (Sandbox Code Playgroud)
用法:
template <typename B, typename D>
enable_if_t<is_base_of_v<B, D>, Foo> some_function(B & b, D & d) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)
_t事实上,表单的"类型"别名是作为C++ 14标准库的一部分计划的,参见[meta.type.synop].
舒适的C++ 11 using编译器设施简单......
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
Run Code Online (Sandbox Code Playgroud)
支持更受using攻击的编译器,例如Visual C++ 12.0及更早版本(它理解基本用途,using但在使用上下文之类的东西越多越不可靠enable_if)是更多涉及,建立在C++ 03-风格解决方案如......
namespace cppx {
using std::enable_if;
template<
class Condition_type,
class Result_type = void,
class enabled = typename enable_if<Condition_type::value, void>::type
>
struct If_T_
{
typedef Result_type T;
typedef Result_type type;
};
} // namespace cppx
Run Code Online (Sandbox Code Playgroud)
这基本上只提供了一个更易读的名称,并省去::value了条件.为了还免去typename和::type我使用的宏.但由于表达式通常是模板表达式,因此预处理器可能会将逗号解释为参数分隔符,以便预处理器可以看到多个参数.
我使用的解决方案(C++ 03的时间结束了)是使用C99/C++ 11 可变参数宏,...
#define CPPX_IF_( ... ) \
typename cppx::If_T_< __VA_ARGS__ >::T
Run Code Online (Sandbox Code Playgroud)
可以定义相应的宏以使用此功能而无需使用typename.
完整列表,文件rfc/cppx/utility/If_.h:
#pragma once
// Copyright (c) 2013 Alf P. Steinbach
#include <type_traits> // std::enable_if
#define CPPX_IF_( ... ) \
typename cppx::If_T_< __VA_ARGS__ >::T
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;
template<
class Condition_type,
class Result_type = void,
class enabled = typename enable_if<Condition_type::value, void>::type
>
struct If_T_
{
typedef Result_type T;
typedef Result_type type;
};
} // namespace cppx
Run Code Online (Sandbox Code Playgroud)
此外,为了完整性,Is_a_简单定义为......
template< class Base, class Derived_or_eq >
using Is_a_ = std::is_base_of<Base, Derived_or_eq>;
Run Code Online (Sandbox Code Playgroud)
这是usingVisual C++ 12.0确实理解的用法.
为了能够在不写入任何地方的情况下使用复合条件::value,以下定义派上用场.基本上这些是对类型进行操作的布尔运算符.或许特别值得注意的是一般的异或运算符,它没有用二进制XOR(例如!=)实现:这将产生一个检查奇数个true值的运算符,除了特殊的实际效用之外没什么用处.恰好有两个参数的情况.
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
Run Code Online (Sandbox Code Playgroud)
免责声明:没有任何代码经过广泛测试,模板元编程领域的C++编译器怪癖很常见.
我们有C++ 03和C++ 11和C++ 14解决方案,但缺少Concepts Lite:
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(); }
Run Code Online (Sandbox Code Playgroud)
或者更简洁:
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(); }
Run Code Online (Sandbox Code Playgroud)
我强烈建议浏览一下Concepts Lite论文的教程(第2部分),以了解在我们离开我们的enable_if领主之后世界会变得多好.