从函数类型中删除所有限定符
Stripping all qualifiers from a function type
给定一个可能的varargs函数类型,可能有一个cv-qualifier-seq和一个ref-qualifier,是否有可能编写一个类型特征来剥离所有限定符而不写4 * 3 * 2 = 24个部分特化?
template<class T>
struct strip_function_qualifiers;
template<class R, class... Args>
struct strip_function_qualifiers<R(Args...)> { using type = R(Args...); };
template<class R, class... Args>
struct strip_function_qualifiers<R(Args..., ...)> { using type = R(Args..., ...); };
template<class R, class... Args>
struct strip_function_qualifiers<R(Args...) const> { using type = R(Args...); };
template<class R, class... Args>
struct strip_function_qualifiers<R(Args..., ...) const > { using type = R(Args..., ...); };
template<class R, class... Args>
struct strip_function_qualifiers<R(Args...) const &> { using type = R(Args...); };
template<class R, class... Args>
struct strip_function_qualifiers<R(Args..., ...) const & > { using type = R(Args..., ...); };
// etc. etc. for each possible combination (24 in total)
随着新的事务内存 TS 增加了transaction_safe
,这是否意味着我们需要为此编写 48 个部分专用化?
编辑:引用这些奇怪的函数类型的描述([dcl.fct]/p6,引用N4140):
具有 cv 限定符序列或引用限定符的函数类型 (包括由 typedef-name (7.1.3, 14.1)命名的类型)应出现 仅作为:
- 非静态成员函数的函数类型,
- 指向成员的指针所引用的函数类型,
函数类型- 定义声明或别名声明的顶级函数类型,
- 类型参数的默认参数中的类型 ID (14.1),或
- 类型参数的模板参数的类型 ID (14.3.1)。
[ 示例:
typedef int FIC(int) const; FIC f; // ill-formed: does not declare a member function struct S { FIC f; // OK }; FIC S::*pm = &S::f; // OK
— 结束示例 ]
函数中 cv 限定符序列的影响 声明符与在 函数类型。在后一种情况下,将忽略 cv 限定符。 [注意:具有 cv 限定符 seq 的函数类型不是 符合CV标准的类型;没有符合 CV 标准的函数类型。— 完 注 ] [ 示例:
typedef void F(); struct S { const F f; // OK: equivalent to: void f(); };
— 结束示例 ]
返回类型、参数类型列表、 ref-qualifier 和 cv-qualifier-seq(但不是默认参数 (8.3.6) 或异常规范 (15.4) )是 函数类型。[注意:在 指向函数、引用的指针的赋值和初始化 到函数,以及指向成员函数的指针。— 尾注 ]
我认为没有办法解决这个问题 - 定义一次并尽可能重用它。
当限定符是顶级时,如此大量的专业化是可以避免的 - 在这种情况下,我们可以使用 std::remove_cv
或 std::remove_reference
,删除每一步中的所有正交限定符。不幸的是,这不适用于您引用的段落中解释的函数:例如 cv-qualifier 是函数类型的一部分,而不是顶级的。 void() const
是与void()
根本不同的类型,因此两者必须由两个不同的部分特化来匹配。
不过,您可以使用宏缩短所有专业化:
#define REM_CTOR(...) __VA_ARGS__
#define SPEC(var, cv, ref)
template <typename R, typename... Args>
struct strip_function_qualifiers<R(Args... REM_CTOR var) cv ref >
{using type = R(Args... REM_CTOR var);};
#define REF(var, cv) SPEC(var, cv,) SPEC(var, cv, &) SPEC(var, cv, &&)
#define CV(var) REF(var,) REF(var, const)
REF(var, volatile) REF(var, const volatile)
template <typename> struct strip_function_qualifiers;
CV(()) CV((,...))
演示。
Boost.PP也是可能的:
#include <boost/preprocessor/tuple/enum.hpp>
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/seq/for_each_product.hpp>
#define REF (&&)(&)()
#define CV (const volatile)(const)(volatile)()
#define VAR (())((,...)) // Had to add a comma here and use rem_ctor below,
// otherwise Clang complains about ambiguous ellipses
#define SPEC(r, product)
template <typename R, typename... Args>
struct strip_function_qualifiers<R(Args... BOOST_PP_TUPLE_ENUM(
BOOST_PP_SEQ_ELEM(0, product)))
BOOST_PP_SEQ_ELEM(1, product)
BOOST_PP_SEQ_ELEM(2, product)>
{using type = R(Args... BOOST_PP_TUPLE_ENUM(BOOST_PP_SEQ_ELEM(0, product)));};
template <typename> struct strip_function_qualifiers;
BOOST_PP_SEQ_FOR_EACH_PRODUCT(SPEC, (VAR)(CV)(REF))
演示。添加新的限定符(例如 transaction_safe
或 transaction_safe_noinherit
时,这两种方法都不会得到更长的时间。
这是一个修改后的SPEC
,它也定义了某些特征成员。
#include <type_traits>
#include <boost/preprocessor/tuple/size.hpp>
// […]
#define SPEC(r, product)
template <typename R, typename... Args>
struct strip_function_qualifiers<R(Args... BOOST_PP_TUPLE_ENUM(
BOOST_PP_SEQ_ELEM(0, product)))
BOOST_PP_SEQ_ELEM(1, product)
BOOST_PP_SEQ_ELEM(2, product)>
{
using type = R(Args... BOOST_PP_TUPLE_ENUM(BOOST_PP_SEQ_ELEM(0, product)));
private:
using cv_type = int BOOST_PP_SEQ_ELEM(1, product);
using ref_type = int BOOST_PP_SEQ_ELEM(2, product);
public:
using is_const = std::is_const<cv_type>;
using is_volatile = std::is_volatile<cv_type>;
using is_ref_qualified = std::is_reference<ref_type>;
using is_lvalue_ref_qualified = std::is_lvalue_reference<ref_type>;
using is_rvalue_ref_qualified = std::is_rvalue_reference<ref_type>;
using is_variadic = std::integral_constant<bool,
!!BOOST_PP_TUPLE_SIZE(BOOST_PP_SEQ_ELEM(0, product))>;
};
- 为什么我的双向链表删除函数会删除多个节点?
- unique_ptr实现接口时对已删除函数的引用
- 可视代码 删除函数括号内的空格
- 从尝试引用已删除函数的矢量 C++ 中删除对象
- 试图引用已删除函数数组的相等运算符
- 双链表堆栈删除函数不起作用
- 是否需要删除函数中未使用的新结构?
- C++引用已删除函数错误
- 删除函数环境中C++输入 R 对象
- 删除函数中的对象C++
- 在 C++ 中使用删除函数的不同方式
- C++错误:C2280 - 引用已删除函数的编译器错误?
- C++,删除函数/迭代进程中定义的动态数组
- 删除函数 c++ 的读取访问冲突异常
- 如何对此自定义C 列表类实现删除函数
- 双向链表问题(特别是复制构造函数和删除函数)
- 引用 std::atomic <bool>的已删除函数错误
- 在删除函数自由度的指针后,为什么我会得到核心转储
- C++删除函数
- 返回 C++11 中已删除函数的类型