如何确保作为模板参数传递的函数类型不修改参数?
How to ensure that function type passed as template argument does not modify arguments?
考虑这个模板
template<typename FunctionType>
void foo(FunctionType && function)
{
Bar b;
bar.mutateState();
function(bar);
}
我想确保 function
不会变异 bar
。以下不应该编译。
foo([](Bar &){});
但是,这两行都应该编译。
foo([](const Bar &){});
foo([](Bar){});
可以使用哪些技巧?越简单越好,但我更喜欢模板类型自省而不是 std::function
或函数指针签名。
您可以修改 foo
以使用 bar
的 const
版本调用 function
:
template<typename FunctionType>
void foo(FunctionType && function)
{
Bar bar;
bar.mutateState();
auto const & c_bar = bar;
function(c_bar);
}
发帖后我意识到我可以做以下事情
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
。
最简单的方法是使用as_const
效用函数(C++17 起):
template<typename FunctionType>
void foo(FunctionType && function)
{
Bar b;
bar.mutateState();
function(std::as_const(bar));
}
你可以明确说明你的类型。
#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)
{});
}
使用 SFINAE,您可以:
template<typename FunctionType>
auto foo(FunctionType && function)
-> decltype(function(std::declval<const Bar&>()), void())
{
Bar bar;
bar.mutateState();
function(bar);
}
考虑这个模板
template<typename FunctionType>
void foo(FunctionType && function)
{
Bar b;
bar.mutateState();
function(bar);
}
我想确保 function
不会变异 bar
。以下不应该编译。
foo([](Bar &){});
但是,这两行都应该编译。
foo([](const Bar &){});
foo([](Bar){});
可以使用哪些技巧?越简单越好,但我更喜欢模板类型自省而不是 std::function
或函数指针签名。
您可以修改 foo
以使用 bar
的 const
版本调用 function
:
template<typename FunctionType>
void foo(FunctionType && function)
{
Bar bar;
bar.mutateState();
auto const & c_bar = bar;
function(c_bar);
}
发帖后我意识到我可以做以下事情
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
。
最简单的方法是使用as_const
效用函数(C++17 起):
template<typename FunctionType>
void foo(FunctionType && function)
{
Bar b;
bar.mutateState();
function(std::as_const(bar));
}
你可以明确说明你的类型。
#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)
{});
}
使用 SFINAE,您可以:
template<typename FunctionType>
auto foo(FunctionType && function)
-> decltype(function(std::declval<const Bar&>()), void())
{
Bar bar;
bar.mutateState();
function(bar);
}