rapidcheck icon indicating copy to clipboard operation
rapidcheck copied to clipboard

Can't print values of structure even after overloading streaming operator

Open Makogan opened this issue 5 years ago • 3 comments

The gist of the problem is described in this stack overflow post: https://stackoverflow.com/users/6202327/makogan?tab=questions

I tried doing what the documentation specifies but my output is still ??> I was hoping I could find a solution here.

Thank you in advance.

Makogan avatar Jun 28 '20 21:06 Makogan

Please next time link the actual question instead of all your SO questions. The API for displaying is documented here: https://github.com/emil-e/rapidcheck/blob/master/doc/displaying.md

TL;DR: overload

std::ostream &operator<<(std::ostream &, const T &)

or

void showValue(const T &t, std::ostream &os)

bkrmendy avatar Nov 22 '20 12:11 bkrmendy

I am having this same issue.

I can reproduce using the classify example by forcing one of the tests to fail with RC_ASSERT(false);, giving the following output:

Using configuration: seed=14471205679451365402

- RC_TAG
Falsifiable after 1 tests

std::tuple<User>:
(<???>)

/home/wolfie/Program/mycad-geometry/test/rapidcheck/examples/classify/main.cpp:31:
RC_ASSERT(false)

Expands to:
false

- RC_CLASSIFY
OK, passed 100 tests
 5.00% - user.username.empty()

Some of your RapidCheck properties had failures. To reproduce these, run with:
RC_PARAMS="reproduce=BYgUD9FVBdkGgB1ykzA1IrBYQtM5MQNyaAGULTODUjsGgB1ykzA1IHAABAAAAAAA"

Here is the diff against commit 718868c which produces this output:

--- a/examples/classify/main.cpp
+++ b/examples/classify/main.cpp
@@ -28,7 +28,7 @@ struct Arbitrary<User> {
 } // namespace rc
 
 int main() {
-  rc::check("RC_TAG", [](const User &user) { RC_TAG(user.gender); });
+  rc::check("RC_TAG", [](const User &user) { RC_TAG(user.gender); RC_ASSERT(false)});
 
   rc::check("RC_CLASSIFY",
             [](const User &user) { RC_CLASSIFY(user.username.empty()); });

ezzieyguywuf avatar Jun 28 '21 14:06 ezzieyguywuf

After playing around with this a bit, I've learned the following: first, the classify example doesn't work simply because User did not have operator<< defined. This should probably be updated in order to provide a more fully working example.

More importantly, though, I learned that operator<< must be defined in the same namespace as the object you're define it for. e.g., this minimal example:

#include <rapidcheck.h>
#include <iostream>

namespace ns{
    struct Point {
        Point(){};
        Point(float x, float y, float z) : x(x), y(y), z(z){};
        float x, y, z;
    };
}

std::ostream& operator<< (std::ostream& os, const ns::Point& p)
{
    os << "(" << p.x << "," << p.y << ", " << p.z << ")";
    return os;
}

namespace rc{
    template<>
    struct Arbitrary<ns::Point> {
        static Gen<ns::Point> arbitrary() {
            return gen::build<ns::Point>(
                gen::set(&ns::Point::x),
                gen::set(&ns::Point::y),
                gen::set(&ns::Point::z)
            );
        }
    };
}

int main(void)
{
    ns::Point p(10, 20, 30);

    std::cout << "Hello point! " << p << std::endl;

    rc::check("workinG?",
              [](const ns::Point&){RC_ASSERT(false);});
}

Results in:

std::tuple<ns::Point>:
(<???>)

(among other output).

This is easily fixed with the following diff:

@@ -7,12 +7,12 @@
         Point(float x, float y, float z) : x(x), y(y), z(z){};
         float x, y, z;
     };
-}

-std::ostream& operator<< (std::ostream& os, const ns::Point& p)
-{
-    os << "(" << p.x << "," << p.y << ", " << p.z << ")";
-    return os;
+    std::ostream& operator<< (std::ostream& os, const ns::Point& p)
+    {
+        os << "(" << p.x << "," << p.y << ", " << p.z << ")";
+        return os;
+    }
 }

ezzieyguywuf avatar Jun 29 '21 03:06 ezzieyguywuf