test_issues.cpp 6.76 KB
Newer Older
1
/*
Dean Moldovan's avatar
Dean Moldovan committed
2
    tests/test_issues.cpp -- collection of testcases for miscellaneous issues
3

4
    Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
6
7
8
9

    All rights reserved. Use of this source code is governed by a
    BSD-style license that can be found in the LICENSE file.
*/

Dean Moldovan's avatar
Dean Moldovan committed
10
11
#include "pybind11_tests.h"
#include "constructor_stats.h"
12
#include <pybind11/stl.h>
13
#include <pybind11/operators.h>
14

Wenzel Jakob's avatar
Wenzel Jakob committed
15
16
PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>);

17
18
19
20
21
22
#define TRACKERS(CLASS) CLASS() { print_default_created(this); } ~CLASS() { print_destroyed(this); }
struct NestABase { int value = -2; TRACKERS(NestABase) };
struct NestA : NestABase { int value = 3; NestA& operator+=(int i) { value += i; return *this; } TRACKERS(NestA) };
struct NestB { NestA a; int value = 4; NestB& operator-=(int i) { value -= i; return *this; } TRACKERS(NestB) };
struct NestC { NestB b; int value = 5; NestC& operator*=(int i) { value *= i; return *this; } TRACKERS(NestC) };

23
24
25
void init_issues(py::module &m) {
    py::module m2 = m.def_submodule("issues");

Wenzel Jakob's avatar
Wenzel Jakob committed
26
27
28
29
30
31
#if !defined(_MSC_VER)
    // Visual Studio 2015 currently cannot compile this test
    // (see the comment in type_caster_base::make_copy_constructor)
    // #70 compilation issue if operator new is not public
    class NonConstructible { private: void *operator new(size_t bytes) throw(); };
    py::class_<NonConstructible>(m, "Foo");
32
    m2.def("getstmt", []() -> NonConstructible * { return nullptr; },
Wenzel Jakob's avatar
Wenzel Jakob committed
33
34
35
        py::return_value_policy::reference);
#endif

36
    // #137: const char* isn't handled properly
37
    m2.def("print_cchar", [](const char *s) { return std::string(s); });
38
39

    // #150: char bindings broken
40
    m2.def("print_char", [](char c) { return std::string(1, c); });
41
42

    // #159: virtual function dispatch has problems with similar-named functions
43
    struct Base { virtual std::string dispatch() const {
Wenzel Jakob's avatar
Wenzel Jakob committed
44
        /* for some reason MSVC2015 can't compile this if the function is pure virtual */
45
        return {};
Wenzel Jakob's avatar
Wenzel Jakob committed
46
    }; };
Wenzel Jakob's avatar
Wenzel Jakob committed
47
48

    struct DispatchIssue : Base {
49
50
        virtual std::string dispatch() const {
            PYBIND11_OVERLOAD_PURE(std::string, Base, dispatch, /* no arguments */);
Wenzel Jakob's avatar
Wenzel Jakob committed
51
52
53
        }
    };

54
    py::class_<Base, std::unique_ptr<Base>, DispatchIssue>(m2, "DispatchIssue")
55
        .def(py::init<>())
56
57
        .def("dispatch", &Base::dispatch);

58
    m2.def("dispatch_issue_go", [](const Base * b) { return b->dispatch(); });
Wenzel Jakob's avatar
Wenzel Jakob committed
59
60

    struct Placeholder { int i; Placeholder(int i) : i(i) { } };
61
62

    py::class_<Placeholder>(m2, "Placeholder")
63
        .def(py::init<int>())
64
65
66
        .def("__repr__", [](const Placeholder &p) { return "Placeholder[" + std::to_string(p.i) + "]"; });

    // #171: Can't return reference wrappers (or STL datastructures containing them)
67
    m2.def("return_vec_of_reference_wrapper", [](std::reference_wrapper<Placeholder> p4){
68
69
        Placeholder *p1 = new Placeholder{1};
        Placeholder *p2 = new Placeholder{2};
70
        Placeholder *p3 = new Placeholder{3};
71
72
73
74
        std::vector<std::reference_wrapper<Placeholder>> v;
        v.push_back(std::ref(*p1));
        v.push_back(std::ref(*p2));
        v.push_back(std::ref(*p3));
75
        v.push_back(p4);
76
77
        return v;
    });
78
79
80
81
82

    // #181: iterator passthrough did not compile
    m2.def("iterator_passthrough", [](py::iterator s) -> py::iterator {
        return py::make_iterator(std::begin(s), std::end(s));
    });
Wenzel Jakob's avatar
Wenzel Jakob committed
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

    // #187: issue involving std::shared_ptr<> return value policy & garbage collection
    struct ElementBase { virtual void foo() { } /* Force creation of virtual table */ };
    struct ElementA : ElementBase {
        ElementA(int v) : v(v) { }
        int value() { return v; }
        int v;
    };

    struct ElementList {
        void add(std::shared_ptr<ElementBase> e) { l.push_back(e); }
        std::vector<std::shared_ptr<ElementBase>> l;
    };

    py::class_<ElementBase, std::shared_ptr<ElementBase>> (m2, "ElementBase");

    py::class_<ElementA, std::shared_ptr<ElementA>>(m2, "ElementA", py::base<ElementBase>())
        .def(py::init<int>())
        .def("value", &ElementA::value);

    py::class_<ElementList, std::shared_ptr<ElementList>>(m2, "ElementList")
        .def(py::init<>())
        .def("add", &ElementList::add)
        .def("get", [](ElementList &el){
            py::list list;
            for (auto &e : el.l)
                list.append(py::cast(e));
            return list;
        });
112
113
114

    // (no id): should not be able to pass 'None' to a reference argument
    m2.def("print_element", [](ElementA &el) { std::cout << el.value() << std::endl; });
115
116
117
118

    // (no id): don't cast doubles to ints
    m2.def("expect_float", [](float f) { return f; });
    m2.def("expect_int", [](int i) { return i; });
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

    // (no id): don't invoke Python dispatch code when instantiating C++
    // classes that were not extended on the Python side
    struct A {
        virtual ~A() {}
        virtual void f() { std::cout << "A.f()" << std::endl; }
    };

    struct PyA : A {
        PyA() { std::cout << "PyA.PyA()" << std::endl; }

        void f() override {
            std::cout << "PyA.f()" << std::endl;
            PYBIND11_OVERLOAD(void, A, f);
        }
    };

    auto call_f = [](A *a) { a->f(); };

Wenzel Jakob's avatar
Wenzel Jakob committed
138
139
140
    pybind11::class_<A, std::unique_ptr<A>, PyA>(m2, "A")
        .def(py::init<>())
        .def("f", &A::f);
141

Wenzel Jakob's avatar
Wenzel Jakob committed
142
    m2.def("call_f", call_f);
143
144
145
146

    try {
        py::class_<Placeholder>(m2, "Placeholder");
        throw std::logic_error("Expected an exception!");
Dean Moldovan's avatar
Dean Moldovan committed
147
    } catch (std::runtime_error &) {
148
149
        /* All good */
    }
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

    // Issue #283: __str__ called on uninitialized instance when constructor arguments invalid
    class StrIssue {
    public:
        StrIssue(int i) : val{i} {}
        StrIssue() : StrIssue(-1) {}
        int value() const { return val; }
    private:
        int val;
    };
    py::class_<StrIssue> si(m2, "StrIssue");
    si  .def(py::init<int>())
        .def(py::init<>())
        .def("__str__", [](const StrIssue &si) {
                std::cout << "StrIssue.__str__ called" << std::endl;
                return "StrIssue[" + std::to_string(si.value()) + "]";
                })
        ;

169
    // Issue #328: first member in a class can't be used in operators
170
171
172
    py::class_<NestABase>(m2, "NestABase").def(py::init<>()).def_readwrite("value", &NestABase::value);
    py::class_<NestA>(m2, "NestA").def(py::init<>()).def(py::self += int())
        .def("as_base", [](NestA &a) -> NestABase& { return (NestABase&) a; }, py::return_value_policy::reference_internal);
173
174
    py::class_<NestB>(m2, "NestB").def(py::init<>()).def(py::self -= int()).def_readwrite("a", &NestB::a);
    py::class_<NestC>(m2, "NestC").def(py::init<>()).def(py::self *= int()).def_readwrite("b", &NestC::b);
175
176
177
    m2.def("get_NestA", [](const NestA &a) { return a.value; });
    m2.def("get_NestB", [](const NestB &b) { return b.value; });
    m2.def("get_NestC", [](const NestC &c) { return c.value; });
178
}