如何确保作为模板参数传递的函数类型不会修改参数?

时间:2016-03-22 09:57:18

标签: c++ templates c++11 typetraits

考虑这个模板

template<typename FunctionType>
void foo(FunctionType && function)
{
  Bar b;
  bar.mutateState();
  function(bar);
}

我想确保function不会改变bar。以下内容不应编译。

foo([](Bar &){});

但是,这两行都应该编译。

foo([](const Bar &){});
foo([](Bar){});

可以使用哪些技巧?更简单更好,但我更喜欢std::function或函数指针签名的模板类型内省。

5 个答案:

答案 0 :(得分:3)

您可以修改foo,使用function constbar来调用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)
    {});
}