0

クラスメンバー関数内で関数オブジェクトを定義して、たとえば std::transform 関数で直接使用できるかどうか、またどのようにできるか疑問に思います。
例が少しばかげていることはわかっています。これは、私が直面している問題を示すためのものです。

ファイル「example.h」

class Example {
  public:
  //.. constructor and destructor stuff
    std::string toString() const; //Converts 'mVal' to a std::string

  private:
    std::vector<int> mVal; //Only one digit numbers are allowed ([0-9])
}

ファイル「example.cpp」

std::string Example::toString() const
{ 
  //The functor which should be used in std::transform
  struct {
    char operator()(const int number) {
      char c;
      //"Convert" 'number' to a char
      return c;
    };
  } functor;

  //Transform the integers to char
  std::string str(mVal.size(), '0'); //Allocate enough space
  std::transform(mVal.begin(), mVal.end(), str.begin(), functor);
  return str;

};//toString()

「example.cpp」のように関数オブジェクトをメンバー関数内に直接実装しようとして以来、コードはコンパイルされません。私が得るエラーメッセージは次のとおりです。

error: no matching function for call to ‘transform(__gnu_cxx::__normal_iterator<const int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<const int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Example::toString() const::<anonymous struct>&)’

したがって、std::transform で構造体「ファンクター」を使用すると問題が発生すると思います。誰かが私に何が問題なのか教えてもらえますか?

使用:
Ubuntu Linux での gcc-4.2 コンパイラ。

前もってありがとう、
ルネ。

4

2 に答える 2

4

Alexandreがすでに指摘しているように、関数スコープを持つ(または名前がまったくない)型をテンプレートパラメーターとして使用することはできません。ただし、ローカルタイプの静的メンバー関数をファンクターパラメーターとして使用できます。

int main()
{
    struct F {
        static int fn(int x)
        {
            return x+x;
        }
    }; 

    int v[5]={1,2,3,4,5};
    std::transform(v+0,v+5,v+0,F::fn);
}

関数内でローカル状態にする必要があり、型消去イディオムに頼りたくない場合は、ローカル型をキャストして不正行為を行うことができます。

int main()
{
    struct F {
        int k;
        int call (int n) const 
        {

            return n+k;
        }
        static int fn(void *p, int x)
        {
            return ((F*)p)->call(x); 
        }
    }; 

    int v[5]={1,2,3,4,5};
    F f;
    f.k=123;
    std::transform(v+0,v+5,v+0,std::bind1st(std::ptr_fun(F::fn),(void*)&f));
}
于 2010-08-05T09:29:36.557 に答える
2

残念ながら、これはうまくいきません。標準では、ローカル クラスをテンプレート引数として使用することを許可していないため、このアプローチは失敗します(誰か、標準の関連部分を引用してください)

14.3.1/2: 「ローカル型、リンケージのない型、名前のない型、またはこれらの型のいずれかから複合された型は、テンプレート型パラメーターのテンプレート引数として使用してはなりません。」

C++0x コンパイラにアクセスできる場合でも、これは機能します。

ローカルクラスは強力だったかもしれませんが、その使用は「型消去イディオム」にいくらか制限されています。

struct abstract_foo { ... };

template <typename T>
abstract_foo* make_concrete_foo(...)
{
    struct foo : abstract_foo
    {
        // Depends on T
    };

    return new foo(...);
}
于 2010-08-05T08:59:03.703 に答える