Ale*_*ph0 10 c++ stdtuple c++17
在许多单元测试中,我需要比较仅具有数据成员的简单结构的内容:
struct Object {
int start;
int stop;
std::string message;
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我想写一些类似的东西:
CHECK(object1==object2);
Run Code Online (Sandbox Code Playgroud)
我总是必须实现:
bool operator==(const Object& lhs, const Object& rhs) {
return lhs.start==rhs.start && lhs.stop==rhs.stop && lhs.message=rhs.message;
}
Run Code Online (Sandbox Code Playgroud)
Writing all these comparison functions becomes tedious, but is also prone to errors. Just imagine, what will happen if I add a new data member to Object, but the comparison operator will not be updated.
Then I remembered my knowledge in Haskell and the magic deriving(Eq) directive, which just generates a sane comparison function for free.
How, could I derive something similar in C++?
Happily, I figured out that C++17 comes with a generic operator== and that every struct should be easily convertible to an std::tuple by the virtue of std::make_tuple.
So I boldly tried the following:
#include <tuple>
#include <iostream>
#include <tuple>
template<typename T>
bool operator==(const T& lhs, const T& rhs)
{
auto leftTuple = std::make_tuple(lhs);
auto rightTuple = std::make_tuple(rhs);
return leftTuple==rightTuple;
}
struct Object
{
std::string s;
int i;
double d;
};
int main(int arg, char** args)
{
std::cout << (Object{ "H",1,2. } == Object{ "H",1,2. }) << std::endl;
std::cout << (Object{ "A",2,3. } == Object{ "H",1,2. }) << std::endl;
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
But, unfortunately it just doesn't compile and I really don't know why. Clang tells me:
main.cpp:11:18: error: use of overloaded operator '==' is ambiguous (with operand types
'std::tuple<Object>' and 'std::tuple<Object>')
return leftTuple==rightTuple;
Run Code Online (Sandbox Code Playgroud)
Can I possibly fix this compile error to get my desired behavior?
No, since comparing tuples reverts to comparing the elements of the tuple, so leftTuple == rightTuple tries to compare two Objects which is not possible.
that every struct should be easily convertible to an
std::tupleby the virtue ofstd::make_tuple
No, you'll just get a tuple with one element, the struct.
The trick is to use std::tie:
std::tie(lhs.mem1, lhs.mem2) == std::tie(rhs.mem1, rhs.mem2)
Run Code Online (Sandbox Code Playgroud)
but that has the same problem as your original solution. Unfortunately C++17 doesn't have any facility to avoid this problemyou could write a macro :). But in C++20 you will be able to do:
struct Object
{
std::string s;
int i;
double d;
bool operator==(const Object &) const = default;
};
Run Code Online (Sandbox Code Playgroud)
which will generate the correct comparison operators for Object.
| 归档时间: |
|
| 查看次数: |
132 次 |
| 最近记录: |