摆脱 C++ 中令人讨厌的函数类型的可能方法?

问题描述 投票:0回答:1

所以我最近接触到了C++中所谓的“令人厌恶的函数类型”的怪诞(据我所知源自这篇论文:https://www.open-std.org/jtc1/sc22/ wg21/docs/papers/2015/p0172r0.html)。我想了一会儿,它似乎确实有一定道理,但如果有人以某种方式将它们从语言中完全删除,一切都会变得更加干净和更令人满意。

也许还有其他起源,但是(至少对我来说)令人讨厌的函数类型的大多数问题都来自于处理成员函数。如果我想获取成员函数的类型,我会这样做:

template <typename T>
struct remove_ptr_to_member { using type = T; };

template <typename T, typename class_t>
struct remove_ptr_to_member<T class_t::*> { using type = T; };

struct container {
   void func() const;
};

using member_function_type = typename remove_ptr_to_member<decltype(container::func)>::type;

由于

const
的声明中存在
func()
,删除指向成员的指针部分会给我们留下一个令人讨厌的函数。

如果将不可见的

this
参数放入成员函数的类型中,则可以避免这种情况。然后,通常会导致令人讨厌的函数的东西都将应用于
this
参数(
const
意味着
const this
指针,
&&
意味着对
this
实例的右值引用,等等) ...).

现在,即使您删除了类型的指向成员的指针部分,剩下的也只是一个完全正常的函数类型。这样做的好处是,它会减少您在实现诸如

is_function
之类的事情时必须编写的样板文件的数量。

经典方法:

// primary template
template<class>
struct is_function : std::false_type { };
 
// specialization for regular functions
template<class Ret, class... Args>
struct is_function<Ret(Args...)> : std::true_type {};
 
// specialization for variadic functions such as std::printf
template<class Ret, class... Args>
struct is_function<Ret(Args......)> : std::true_type {};
 
// specialization for function types that have cv-qualifiers
template<class Ret, class... Args>
struct is_function<Ret(Args...) const> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) volatile> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const volatile> : std::true_type {};
// etc... (goes on for a while)

新方法:

// primary template
template <typename>
struct is_function : std::false_type { };

// specialization for regular functions
template<typename Ret, typname... Args>
struct is_function<Ret(Args...)> : std::true_type { };

// specialization for variadic functions such as std::printf
template<typename Ret, typname... Args>
struct is_function<Ret(Args......)> : std::true_type { };

// same thing but with noexcept
template<typename Ret, typname... Args>
struct is_function<Ret(Args...) noexcept> : std::true_type { };
template<typename Ret, typname... Args>
struct is_function<Ret(Args......) noexcept> : std::true_type { };

就这样了。不需要很长的样板,因为所有复杂的事情(

const
volatile
等)都隐藏在第一个参数中。

我很抱歉等了这么久才提出实际问题,但时间已经到了: 有人对此修复有反驳意见吗?它甚至是一个修复程序,也许它不能处理所有需要处理的事情?我想我想知道的是,为什么这不在标准中?如果这是一个好主意,一定有人想到了,对吗?一定有一些我没有考虑到的额外信息,因为这看起来太简单了。

c++ function templates metaprogramming function-qualifier
1个回答
5
投票

几乎完全符合您的建议,C++23 已接受作为带有 显式对象参数的成员函数,如下所示:

struct container {
    void func(this container const&);
};

此函数的类型为

void(container const&)
而不是
void() const
,或者等效地
&container::func
的类型将为
void(*)(container const&)
而不是
void (container::*)() const

参见介绍此新功能的P0847

但这不会改变具有隐式而不是显式对象参数的旧式非静态成员函数需要具有 cvref 限定的函数类型。更改这些函数的类型会破坏大量代码,因此为时已晚。

© www.soinside.com 2019 - 2024. All rights reserved.