c++ 使用单一定义的常数和非常数参数函数重载

b4lqfgs4  于 2022-11-19  发布在  其他
关注(0)|答案(2)|浏览(186)

我有以下2个函数重载:

template<typename F, typename T>
void func(F f, std::vector<T>& v) { ... }

template<typename F, typename T>
void func(F f, const std::vector<T>& v) { ... }

它们的主体是相同的。有没有一种简单的方法可以用一个定义来定义它们,以避免使用C17或更早的标准进行代码重复?
我想澄清一下我希望函数基于std::vector部分进行约束,但我希望允许传递常量和非常量引用。我需要这两个重载的原因是F函数对象将应用于向量,有时F将修改向量,有时它将只观察向量(在第二种情况下,我希望将向量声明为const)。
我想我可以使用C
20的概念来约束函数模板参数,但是我想知道是否有一种简单的方法可以使用C++17或更早版本的标准来实现同样的事情。

ukxgm1gy

ukxgm1gy1#

您不需要require子句来执行sfinae,

#include <vector>
#include <type_traits>

template<typename T>
struct is_vector : std::false_type{};
template<typename ...Args>
struct is_vector<std::vector<Args...>> : std::true_type{};

template<
    typename F,
    typename C,
    std::enable_if_t<is_vector<std::remove_cvref_t<C>>::value,std::nullptr_t> = nullptr
>
void func(F f, C&& v) {
   // ...
}
  • std::remove_cvref_t仍然是c++20,您需要在早期标准中使用std::remove_cv_t<std::remove_reference_t<T>>
vjrehmav

vjrehmav2#

我找到了另一种解决方案,但它仍然会增加一点开销:

template<typename F, typename VecT>
auto func_vec(F f, VecT& vec)
{
  //actual code
}

template<typename F, typename T>
auto func(F f, std::vector<T>& vec) { return func_vec(f, vec); }

template<typename F, typename T>
auto func(F f, const std::vector<T>& vec) { return func_vec(f, vec); }

定义了第三个函数(func_vec),它保存func的实际实现。
请注意,typename VecT可以接受const和非const参数。
func多载只是用来将参数限制为std::vector<T>&型别,不论是否有const限定词。
这个解决方案的优点是它不使用SFINAE,并且相当容易阅读,缺点是您必须为实际实现引入另一个函数模板。

相关问题