考虑这个模板
template<typename FunctionType>
void foo(FunctionType && function)
{
Bar b;
bar.mutateState();
function(bar);
}
我想确保function
不会改变bar
。以下内容不应编译。
foo([](Bar &){});
但是,这两行都应该编译。
foo([](const Bar &){});
foo([](Bar){});
可以使用哪些技巧?更简单更好,但我更喜欢std::function
或函数指针签名的模板类型内省。
答案 0 :(得分:3)
您可以修改foo
,使用function
const
版bar
来调用template<typename FunctionType>
void foo(FunctionType && function)
{
Bar bar;
bar.mutateState();
auto const & c_bar = bar;
function(c_bar);
}
:
$("ul").prevAll("p").addClass("someClass");
答案 1 :(得分:3)
最简单的方法是使用as_const
效用函数(自C ++ 17起):
template<typename FunctionType>
void foo(FunctionType && function)
{
Bar b;
bar.mutateState();
function(std::as_const(bar));
}
答案 2 :(得分:2)
使用SFINAE,您可以:
template<typename FunctionType>
auto foo(FunctionType && function)
-> decltype(function(std::declval<const Bar&>()), void())
{
Bar bar;
bar.mutateState();
function(bar);
}
答案 3 :(得分:0)
发布后我意识到我可以做以下
template<typename T>
typename std::add_const<T>::type &asConst(T &t)
{
return t;
}
template<typename FunctionType>
void Foo(FunctionType && function)
{
Bar bar;
bar.mutateState();
function(asConst(bar));
}
显然,这已包含在C++17
std::as_const
中。
答案 4 :(得分:0)
您可以明确指出您的类型。
#pragma once
class Bar
{
int a;
public:
Bar() : a{0}
{}
void mutateState()
{
++a;
}
};
void foo(void(*function)(const Bar &))
{
Bar bar;
bar.mutateState();
function(bar);
}
int main()
{
foo([](const Bar &)
{});
foo([](Bar)
{});
}