1

テストフレームワーク(tut)を使用していて、再現性が高いことに気付いたので、必要な述語関数を抽象化し始めました。以下は簡単な例です。

それは機能しますが、私はすべてを1行で実行できることを望んでいました。問題は、派生述語クラスをインラインでインスタンス化しようとすると、コンパイルに失敗することです。なぜ何かアイデアはありますか?

#include <string>
#include <functional>
#include <iostream>


using namespace std;


template <class T>
struct TestPredicate : public binary_function<T,T,bool>
{
  virtual bool operator() (const T& expected, const T& data) const = 0;
};

template <class T>
struct IsEqual : public TestPredicate<T>
{
  virtual bool operator() (const T& expected, const T& data) const
  {
    cout << "IsEqual: " << expected << ", " << data << endl;
    return data == expected;
  }
};

template <class T>
struct IsNotEqual : public TestPredicate<T>
{
  virtual bool operator() (const T& expected, const T& data) const 
  {
    cout << "IsNotEqual: " << expected << ", " << data << endl;
    return data != expected;
  }
};

struct Tester
{
  template <class T>
  void test( const T& data, const T& expected, TestPredicate<T>& value_condition ) 
  {
    if ( value_condition( expected, data ) ) 
    {
      cout << "PASSED" << endl;
    }
    else 
    {
      cout << "FAILED" << endl;
    }
  }
};


int main() 
{
  Tester test;

  string data("hello");
  string expected("hello");

  // this doesn't compile with an inline instantiation of IsEqual
  //test.test( data, expected, IsEqual<string>() );   // compilation error (see below)

  // this works with an explicit instantiation of IsEqual
  IsEqual<string> pred;
  test.test( data, expected, pred );

  return 0;
}

コンパイル出力:

test2.cpp: In function ‘int main()’:
test2.cpp:61:48: error: no matching function for call to ‘Tester::test(std::string&, std::string&, IsEqual<std::basic_string<char> >)’
test2.cpp:61:48: note: candidate is:
test2.cpp:40:8: note: void Tester::test(const T&, const T&, TestPredicate<T>&) [with T = std::basic_string<char>]
test2.cpp:40:8: note:   no known conversion for argument 3 from ‘IsEqual<std::basic_string<char> >’ to ‘TestPredicate<std::basic_string<char> >&’

g++4.6.3の使用

4

4 に答える 4

5

他の答えに加えて、仮想関数を使用したランタイムポリモーフィズムは実際には必要ありません。テスターに​​別のテンプレートパラメーターを取得させることができます。

template<class T, class Pred>
void test( const T& data, const T& expected, Pred value_condition ) 
于 2012-07-29T10:10:35.680 に答える
4

メソッドは、両方のインスタンス化で機能するために、述語へTester::testの参照を取得する必要があります。const

于 2012-07-29T09:29:27.953 に答える
2

コンパイラが文句を言う理由の説明は単純であり、...少しがっかりします。

C ++標準では、一時オブジェクト(式によって作成されたものなどIsEqual<string>())をconst参照にバインドできることを除外しています。この場合、その有効期間は参照の有効期間まで延長されます。

Stroustrupは、非定数参照へのバインドがバグの原因になることを恐れていたため、許可されていません。後から考えると、対称性がないことは、多くの場合、より驚くべきことです。VC ++では、非定数参照へのバインドが可能です(拡張機能として)。C ++ 11では、「参照参照」(&&)へのバインドを許可することでバランスがいくらか復元されますが、それでもギャップは残ります。

...そしてあなたが自分自身を見つける不快な状況に私たちを残します。

ウェブ上では、これは最も重要constと呼ばれることがあります。

于 2012-07-29T12:22:29.340 に答える
2

一時オブジェクトは常にconstです。つまり、intest.test( data, expected, IsEqual<string>() ); IsEqual<string>()は型const TestPredicate<T>です。

于 2012-07-29T09:44:16.093 に答える