C++:静态断言仿函数的参数是 const 引用

标签 c++ c++17 metaprogramming template-meta-programming

我正在用 C++17 编写一个模板函数,它接受仿函数 F 作为参数,并且我想限制传入的仿函数只有一个常量引用参数,其中 T 可以是任何类型。

例如:

template <class T> struct my_struct{
    std::vector<T> collection;
    template <class F> std::vector<T> func(F f){
        static_assert(
               // CONDITION HERE!,
               "f's argument is not const reference"
            );

        std::vector<T> ret;

        std::copy_if(
                std::make_move_iterator(this->collection.begin()),
                std::make_move_iterator(this->collection.end()),
                std::inserter(ret, ret.end()),
                f
            );

        return ret;
    }
};

显然,如果 f[](auto v){return true;}func 返回的结果 vector 将为空元素(因为这些元素在添加到结果容器之前已被移动)。因此,我需要将可能的输入仿函数限制为 [](const auto& v){}

我尝试过这样的事情:

static_assert(
        std::is_invocable_v<F, const T&>,
        "f's argument is not const reference"
    );

但是 func([](auto v){}) 不会触发断言,因为 T 在我的情况下是可复制的。 func([](auto& v){}) 也通过了测试,因为 auto 可以是 const T

但我需要将可能的 lambda 限制为 func([](const auto& v){})

最佳答案

您可以编写特征(有其局限性),例如:

template <typename Sig> struct callable_traits;

template <typename Ret, typename ...Args>
struct callable_traits<Ret(*)(Args...)>
{
    using args = std::tuple<Args...>;
};
// add specialization for C-ellipsis too

template <typename Ret, class C, typename ...Args>
struct callable_traits<Ret(C::*)(Args...) const>
{
    using args = std::tuple<Args...>;
};
// add specialization for variant with C-ellipsis, cv-qualifier, ref-qualifier

template <class C>
struct callable_traits<C> : callable_traits<&C::operator()>{};

特征的限制:不处理模板化的 operator() (对于通用 lambda)、重载的 operator()

然后

template <class T> struct my_struct{
    template <class F> void func(F f){
        static_assert(
               std::is_same_v<std::tuple<const T&>, typename callable_traits<F>::args>,
               "f's argument is not const reference"
            );

        // here goes some code which can possibly call f with rvalue
        // reference argument, so I want to avoid situation when the
        // argument object is moved or modified. I don't have control
        // over this code because it an STL algorithm.
    }
};

关于C++:静态断言仿函数的参数是 const 引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65888788/

相关文章:

c++ - 使用 std::basic_istringstream<unsigned short> 时的 std::bad_cast

c++ - 在 C++ 的元编程中保护从非 const-volatile 类型到 const-volatile 的赋值的正确方法是什么?

c++ - 在运算符表达式上下文中纠正重载解析的内置运算符候选的行为

ruby - Ruby 中的 method_missing 陷阱

Python:在类主体中动态创建子类

c++ - gdb 启动但不逐行执行

c++ - 在头文件中使用 constexpr

c++ - 为什么指向整数的指针递增 4 个字节?

c++ - 如何解释 std::launder 的可达性要求?

c++ - 递归折叠参数包以解析占位符类型