复制简历参考限定词的类型特征 [英] Type trait for copying cv reference qualifiers
问题描述
在 C ++ 中编写类似库的代码,我发现 copy_cv_reference_t
类型特征特别有必要:
Writing library-like code in C++ I found there is particular need in copy_cv_reference_t
type trait:
struct A;
struct B;
static_assert(std::is_same< copy_cv_reference_t< A , B >, B >{});
static_assert(std::is_same< copy_cv_reference_t< A const , B >, B const >{});
static_assert(std::is_same< copy_cv_reference_t< volatile A , B >, volatile B >{});
static_assert(std::is_same< copy_cv_reference_t< volatile A const , B >, volatile B const >{});
static_assert(std::is_same< copy_cv_reference_t< A &, B >, B & >{});
static_assert(std::is_same< copy_cv_reference_t< A const &, B >, B const & >{});
static_assert(std::is_same< copy_cv_reference_t< volatile A &, B >, volatile B & >{});
static_assert(std::is_same< copy_cv_reference_t< volatile A const &, B >, volatile B const & >{});
static_assert(std::is_same< copy_cv_reference_t< A &&, B >, B && >{});
static_assert(std::is_same< copy_cv_reference_t< A const &&, B >, B const && >{});
static_assert(std::is_same< copy_cv_reference_t< volatile A &&, B >, volatile B && >{});
static_assert(std::is_same< copy_cv_reference_t< volatile A const &&, B >, volatile B const && >{});
我通过两种方法为自己发明了这种方法:通过类型限定符的id和仅通过SFINAE.
I invent it for myself using two approaches: via means of id of type qualifiers and via SFINAE only.
#include <type_traits>
#if 1
enum class type_qual_id
{
value,
const_value,
lref,
const_lref,
rref,
const_rref,
volatile_value,
volatile_const_value,
volatile_lref,
volatile_const_lref,
volatile_rref,
volatile_const_rref,
};
template< type_qual_id tqid, typename type > struct add_type_qualifier;
template< typename to > struct add_type_qualifier< type_qual_id::value , to > { using type = to ; };
template< typename to > struct add_type_qualifier< type_qual_id::const_value , to > { using type = to const ; };
template< typename to > struct add_type_qualifier< type_qual_id::lref , to > { using type = to & ; };
template< typename to > struct add_type_qualifier< type_qual_id::const_lref , to > { using type = to const & ; };
template< typename to > struct add_type_qualifier< type_qual_id::rref , to > { using type = to &&; };
template< typename to > struct add_type_qualifier< type_qual_id::const_rref , to > { using type = to const &&; };
template< typename to > struct add_type_qualifier< type_qual_id::volatile_value , to > { using type = volatile to ; };
template< typename to > struct add_type_qualifier< type_qual_id::volatile_const_value, to > { using type = volatile to const ; };
template< typename to > struct add_type_qualifier< type_qual_id::volatile_lref , to > { using type = volatile to & ; };
template< typename to > struct add_type_qualifier< type_qual_id::volatile_const_lref , to > { using type = volatile to const & ; };
template< typename to > struct add_type_qualifier< type_qual_id::volatile_rref , to > { using type = volatile to &&; };
template< typename to > struct add_type_qualifier< type_qual_id::volatile_const_rref , to > { using type = volatile to const &&; };
template< type_qual_id tqid, typename to >
using add_qualifier_t = typename add_type_qualifier< tqid, to >::type;
template< typename type > constexpr type_qual_id get_type_qualifier_id = type_qual_id::value ;
template< typename type > constexpr type_qual_id get_type_qualifier_id< type const > = type_qual_id::const_value ;
template< typename type > constexpr type_qual_id get_type_qualifier_id< type & > = type_qual_id::lref ;
template< typename type > constexpr type_qual_id get_type_qualifier_id< type const & > = type_qual_id::const_lref ;
template< typename type > constexpr type_qual_id get_type_qualifier_id< type && > = type_qual_id::rref ;
template< typename type > constexpr type_qual_id get_type_qualifier_id< type const && > = type_qual_id::const_rref ;
template< typename type > constexpr type_qual_id get_type_qualifier_id< volatile type > = type_qual_id::volatile_value ;
template< typename type > constexpr type_qual_id get_type_qualifier_id< volatile type const > = type_qual_id::volatile_const_value;
template< typename type > constexpr type_qual_id get_type_qualifier_id< volatile type & > = type_qual_id::volatile_lref ;
template< typename type > constexpr type_qual_id get_type_qualifier_id< volatile type const & > = type_qual_id::volatile_const_lref ;
template< typename type > constexpr type_qual_id get_type_qualifier_id< volatile type && > = type_qual_id::volatile_rref ;
template< typename type > constexpr type_qual_id get_type_qualifier_id< volatile type const && > = type_qual_id::volatile_const_rref ;
template< typename from, typename to >
using copy_cv_reference_t = add_qualifier_t< get_type_qualifier_id< from >, to >;
#else
#include <type_traits>
template< typename from, typename to >
struct copy_cv
{
using type = to;
};
template< typename from, typename to >
struct copy_cv< from const, to >
: copy_cv< from, to const >
{
};
template< typename from, typename to >
struct copy_cv< volatile from, to >
: copy_cv< from, volatile to >
{
};
template< typename from, typename to >
struct copy_cv< volatile from const, to >
: copy_cv< from, volatile to const >
{
};
template< typename from, typename to >
struct copy_reference
{
using type = to;
};
template< typename from, typename to >
struct copy_reference< from &, to >
: copy_reference< from, to & >
{
};
template< typename from, typename to >
struct copy_reference< from &&, to >
: copy_reference< from, to && >
{
};
template< typename from, typename to >
using copy_cv_reference_t = typename copy_reference< from, typename copy_cv< std::remove_reference_t< from >, to >::type >::type;
#endif
第一种方法看起来有些虚假,但提供了"type qualifiers id"作为附加的一面,而后一种方法在某些情况下很有用.第二种方法本质上是两步走.它可能有缺点.此外,它还涉及到 std :: remove_reference_t
来揭示cv限定的类型.
First approach looks slightly more artificial, but provides a "type qualifiers id" as additional side and latter can be useful in some situations. Second approach is inherently two-step one. It could has downsides. In addition, it involve std::remove_reference_t
to reveal the cv-qualified type.
一方面,我知道标准允许实现具有内在"类型特征.另一方面,当前的 C ++ 标准中目前没有类型特征.
On the one hand, I know standard allows for implementations to have an "intrinsic" type traits. On the other hand, there is no the type trait currently in contemporary C++ standard.
copy_cv_reference_t
类型特征的最佳实现是什么?不仅在上述两个之间.有更好的方法来实施它吗?有相应的建议吗?
What is the best implementation of copy_cv_reference_t
type trait? Not only between above two. Are there better approaches to implement it? Is there corresponding proposal?
那命名呢?ID的顺序如何?
What about naming? What about order of ids?
推荐答案
我还没有遇到任何需要像这样的类型特征的用例,而且我不知道有任何提议.因此,我只能提供一种更紧凑,恕我直言更易于理解的实现:
I haven't encountered any use-case which required a type-trait like that and I am not aware of any proposal. I can therefore only offer an implementation which is more compact and IMHO more simple to understand:
template<typename T,typename U>
struct copy_cv_reference
{
private:
using R = std::remove_reference_t<T>;
using U1 = std::conditional_t<std::is_const<R>::value, std::add_const_t<U>, U>;
using U2 = std::conditional_t<std::is_volatile<R>::value, std::add_volatile_t<U1>, U1>;
using U3 = std::conditional_t<std::is_lvalue_reference<T>::value, std::add_lvalue_reference_t<U2>, U2>;
using U4 = std::conditional_t<std::is_rvalue_reference<T>::value, std::add_rvalue_reference_t<U3>, U3>;
public:
using type = U4;
};
template<typename T,typename U>
using copy_cv_reference_t = typename copy_cv_reference<T,U>::type;
是否发现改进是主观的.
Whether you find it an improvement is subjective.
这篇关于复制简历参考限定词的类型特征的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!