13

怠惰な開発者として、私はこのトリックを使用してデフォルトの関数を指定するのが好きです。

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*/ますか?

4

6 に答える 6

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);
    }
}
于 2013-03-04T13:25:53.763 に答える
3

これを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のバージョンを見ることができます。

于 2013-03-04T13:22:45.850 に答える
2

boost :: phoenixは、完全な機能ツールボックスを提供します。ここで、「arg1」はIDのIDです;-)

#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);
  }
}
于 2013-03-04T15:14:56.187 に答える
1

独自のIDファンクターを作成できます。

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);
  }
}
于 2013-03-04T13:24:03.427 に答える
1

ブースト付きの次のバリアントがあります。

template <class Type, unsigned int Size, class Function = boost::function<Type(Type)>>
void index(std::array<Type, Size> &x, Function&& f = boost::bind(std::plus<Type>(), 0, _1))
于 2020-02-11T18:18:22.510 に答える
0

これに対処する方法は、2つの異なる機能を持つことです。デフォルトのパラメータを使用しないのは非常に正しいと思います。

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
}
于 2018-12-25T00:15:43.757 に答える