我正在使用测试框架(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
答案 0 :(得分:5)
除了其他答案之外,您并不需要虚拟功能的运行时多态性。您可以让测试人员使用另一个模板参数:
template<class T, class Pred>
void test( const T& data, const T& expected, Pred value_condition )
答案 1 :(得分:4)
您的Tester::test
方法需要对谓词进行const
引用才能使用这两个实例。
答案 2 :(得分:2)
临时对象始终是const,test.test( data, expected, IsEqual<string>() );
IsEqual<string>()
中的const TestPredicate<T>
类型。
答案 3 :(得分:2)
编译器抱怨的原因解释既简单又有点令人沮丧。
C ++标准规定临时对象(例如由表达式IsEqual<string>()
创建)可以绑定到const引用,在这种情况下,它的生命周期将扩展到引用的生命周期。
因为Stroustrup担心绑定到非const引用只会是bug的来源,所以不允许这样做。事后来看,事实证明,缺乏对称性往往更令人惊讶; VC ++允许绑定到非const引用(作为扩展)。在C ++ 11中,通过允许绑定到“引用引用”(&&
)来稍微恢复平衡,尽管它仍然存在差距......
......让我们处于你发现自己的不愉快境地。
在网络上,这可以称为Most important const
。