1

我正在使用一个测试框架(tut)并注意到很多可重复性,所以我开始抽象出我需要的谓词函数。下面是一个简化的例子。

它有效,但我希望我能在一行中做到这一点。问题是当我尝试内联实例化派生谓词类时,它无法编译。任何想法为什么?

#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

临时对象始终为 const,即方式test.test( data, expected, IsEqual<string>() ); IsEqual<string>()为 类型const TestPredicate<T>

于 2012-07-29T09:44:16.093 回答
2

编译器为什么抱怨的解释既简单又……有点令人沮丧。

C++ 标准排除了临时对象(例如由表达式创建的IsEqual<string>())可以绑定到 const 引用,在这种情况下,它的生命周期会扩展到引用的生命周期。

由于 Stroustrup 担心绑定到非 const 引用只会成为错误的来源,因此不允许这样做。事后看来,缺乏对称性往往更令人惊讶。VC++ 允许绑定到非常量引用(作为扩展)。&&在 C++11 中,通过允许绑定到“引用引用”(

...并让我们陷入您发现自己所处的不愉快的境地。

在网络上,这可能被称为最重要const的。

于 2012-07-29T12:22:29.340 回答