只返回传递值的默认函数?

时间:2013-03-04 13:16:59

标签: c++ templates c++11 lambda std-function

作为一个懒惰的开发人员,我喜欢使用这个技巧来指定一个默认函数:

template <class Type, unsigned int Size, class Function = std::less<Type> >
void arrange(std::array<Type, Size> &x, Function&& f = Function())
{
    std::sort(std::begin(x), std::end(x), f);
}

但我在一个非常特殊的情况下遇到了一个问题,如下所示:

template <class Type, unsigned int Size, class Function = /*SOMETHING 1*/>
void index(std::array<Type, Size> &x, Function&& f = /*SOMETHING 2*/)
{
    for (unsigned int i = 0; i < Size; ++i) {
        x[i] = f(i);
    }
}

在这种情况下,我希望默认函数相当于:[](const unsigned int i){return i;}(一个只返回传递值的函数)。

为了做到这一点,我需要写什么而不是/*SOMETHING 1*//*SOMETHING 2*/

6 个答案:

答案 0 :(得分:19)

没有标准的仿函数可以做到这一点,但写起来很容易(尽管确切的形式是有争议的):

struct identity {
    template<typename U>
    constexpr auto operator()(U&& v) const noexcept
        -> decltype(std::forward<U>(v))
    {
        return std::forward<U>(v);
    }
};

可以使用如下:

template <class Type, std::size_t Size, class Function = identity>
void index(std::array<Type, Size> &x, Function&& f = Function())
{
    for (unsigned int i = 0; i < Size; ++i) {
        x[i] = f(i);
    }
}

答案 1 :(得分:2)

这称为identity功能。不幸的是,它不是C ++标准的一部分,但你可以自己轻松地构建一个。


如果您碰巧使用g ++,则可以使用-std=gnu++11然后

激活其扩展程序
#include <array>
#include <ext/functional>

template <class Type, std::size_t Size, class Function = __gnu_cxx::identity<Type> >
void index(std::array<Type, Size> &x, Function&& f = Function())
{
    for (unsigned int i = 0; i < Size; ++i) {
        x[i] = f(i);
    }
}

也许它将在C ++ 20中提供,请参阅std::identity。在此之前,您可以在boost::compute::identity查看boost的版本。

答案 2 :(得分:2)

boost :: phoenix提供了一个完整的功能工具箱,这里'arg1'是身份的标识; - )

#include <boost/phoenix/core.hpp>

template <class X, class Function = decltype(boost::phoenix::arg_names::arg1)>
void index(X &x, Function f = Function()) {
    for (std::size_t i = 0; i < x.size(); ++i) {
            x[i] = f(i);
  }
}

答案 3 :(得分:1)

您可以构建自己的身份仿函数:

template <typename T>
class returnIdentifyFunctor
{
  public:
     auto operator ()(  T &&i ) -> decltype( std::forward<T>(i) )
    {
      return std::move(i);
    }
};

template <class Type, unsigned int Size, class Function = returnIdentifyFunctor<Type>>
void index(std::array<Type, Size> &x, Function&& f = Function() )
 {
    for (unsigned int i = 0; i < Size; ++i) {
            x[i] = f(i);
  }
}

答案 4 :(得分:1)

boost具有以下变体:

<div class="main flex down fixed-bottom" >
<mat-toolbar class="colour">
    <mat-toolbar-row>

        <div class=" icons row justify-content-between"> 
            <button mat-icon-button class="icons col-xs-3" >
                <mat-icon>home</mat-icon>
            </button>
            <button mat-icon-button class="icons col-xs-3" >
                <mat-icon>email</mat-icon>
            </button>
            <button mat-icon-button  class="icons col-xs-3">
                <mat-icon>add_comment</mat-icon>
            </button>
            <button mat-icon-button class="icons col-xs-3" >
                <mat-icon>title</mat-icon>
            </button>
        </div>

    </mat-toolbar-row>
</mat-toolbar>
</div>

答案 5 :(得分:0)

一种解决方法是具有两个不同的功能。我发现使用默认参数非常理智( not )。

template <class Type, unsigned int Size, class Function>
void index(std::array<Type, Size> &x, Function&& f){
    for(unsigned int i = 0; i < Size; ++i) x[i] = f(i);
}

template<class Type, unsigned int Size>
void index(std::array<Type, Size> &x){
    return index(x, [](unsigned int i){return i;});                      // C++11 in this case
                //, [](auto&& e){return std::forward<decltype(e)>(e)};); // C++14 in a more general case
                //, std::identity); // C++20 in general
}