【发布时间】:2021-04-29 11:53:47
【问题描述】:
我正在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 返回的结果向量将包含空元素(因为这些元素在添加到结果容器之前已被移动)。所以,我需要将可能的输入函子限制为[](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){})。
【问题讨论】:
-
"
auto本身可以是const T&" - 不能。它是一种价值类型。它通过了测试,因为类型是可复制的。你想达到什么目的?为什么“仅通过 const-ref”似乎是解决方案? -
@StoryTeller-UnslanderMonica 对,因为它是可复制的。正如我所说,我试图阻止
F的参数被移动或修改。 -
听起来你只需要对传递给函数的东西进行右值到左值的转换。使用
const auto&& lvalue_temp = expression_that_generates_temporary;然后将lvalue_temp传递给f将确保它不能被移动或修改。 -
那为什么不直接通过
std::as_const传递呢?它会触发修改(不考虑const_cast,但我们应该假设函子是理智的)。如果不广泛,您也可以制作本地副本。让函子拥有这些。 -
我已经在问题中添加了更多信息,我拥有或多或少的确切代码。可以看到,我正在使用移动迭代器和
std::copy_if。这可能会提供有关我需要的更多信息。
标签: c++ c++17 metaprogramming template-meta-programming