Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
gaoqiong
pybind11
Commits
4e3d9fea
Commit
4e3d9fea
authored
May 22, 2020
by
Eric Cousineau
Committed by
Wenzel Jakob
May 31, 2020
Browse files
operators: Explicitly expose `py::hash(py::self)`
Add warnings about extending STL
parent
53095730
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
41 additions
and
3 deletions
+41
-3
include/pybind11/operators.h
include/pybind11/operators.h
+5
-0
tests/test_operator_overloading.cpp
tests/test_operator_overloading.cpp
+24
-1
tests/test_operator_overloading.py
tests/test_operator_overloading.py
+12
-2
No files found.
include/pybind11/operators.h
View file @
4e3d9fea
...
@@ -147,6 +147,9 @@ PYBIND11_INPLACE_OPERATOR(ixor, operator^=, l ^= r)
...
@@ -147,6 +147,9 @@ PYBIND11_INPLACE_OPERATOR(ixor, operator^=, l ^= r)
PYBIND11_INPLACE_OPERATOR
(
ior
,
operator
|=
,
l
|=
r
)
PYBIND11_INPLACE_OPERATOR
(
ior
,
operator
|=
,
l
|=
r
)
PYBIND11_UNARY_OPERATOR
(
neg
,
operator
-
,
-
l
)
PYBIND11_UNARY_OPERATOR
(
neg
,
operator
-
,
-
l
)
PYBIND11_UNARY_OPERATOR
(
pos
,
operator
+
,
+
l
)
PYBIND11_UNARY_OPERATOR
(
pos
,
operator
+
,
+
l
)
// WARNING: This usage of `abs` should only be done for existing STL overloads.
// Adding overloads directly in to the `std::` namespace is advised against:
// https://en.cppreference.com/w/cpp/language/extending_std
PYBIND11_UNARY_OPERATOR
(
abs
,
abs
,
std
::
abs
(
l
))
PYBIND11_UNARY_OPERATOR
(
abs
,
abs
,
std
::
abs
(
l
))
PYBIND11_UNARY_OPERATOR
(
hash
,
hash
,
std
::
hash
<
L
>
()(
l
))
PYBIND11_UNARY_OPERATOR
(
hash
,
hash
,
std
::
hash
<
L
>
()(
l
))
PYBIND11_UNARY_OPERATOR
(
invert
,
operator
~
,
(
~
l
))
PYBIND11_UNARY_OPERATOR
(
invert
,
operator
~
,
(
~
l
))
...
@@ -160,6 +163,8 @@ PYBIND11_UNARY_OPERATOR(float, float_, (double) l)
...
@@ -160,6 +163,8 @@ PYBIND11_UNARY_OPERATOR(float, float_, (double) l)
NAMESPACE_END
(
detail
)
NAMESPACE_END
(
detail
)
using
detail
::
self
;
using
detail
::
self
;
// Add named operators so that they are accessible via `py::`.
using
detail
::
hash
;
NAMESPACE_END
(
PYBIND11_NAMESPACE
)
NAMESPACE_END
(
PYBIND11_NAMESPACE
)
...
...
tests/test_operator_overloading.cpp
View file @
4e3d9fea
...
@@ -43,6 +43,13 @@ public:
...
@@ -43,6 +43,13 @@ public:
friend
Vector2
operator
-
(
float
f
,
const
Vector2
&
v
)
{
return
Vector2
(
f
-
v
.
x
,
f
-
v
.
y
);
}
friend
Vector2
operator
-
(
float
f
,
const
Vector2
&
v
)
{
return
Vector2
(
f
-
v
.
x
,
f
-
v
.
y
);
}
friend
Vector2
operator
*
(
float
f
,
const
Vector2
&
v
)
{
return
Vector2
(
f
*
v
.
x
,
f
*
v
.
y
);
}
friend
Vector2
operator
*
(
float
f
,
const
Vector2
&
v
)
{
return
Vector2
(
f
*
v
.
x
,
f
*
v
.
y
);
}
friend
Vector2
operator
/
(
float
f
,
const
Vector2
&
v
)
{
return
Vector2
(
f
/
v
.
x
,
f
/
v
.
y
);
}
friend
Vector2
operator
/
(
float
f
,
const
Vector2
&
v
)
{
return
Vector2
(
f
/
v
.
x
,
f
/
v
.
y
);
}
bool
operator
==
(
const
Vector2
&
v
)
const
{
return
x
==
v
.
x
&&
y
==
v
.
y
;
}
bool
operator
!=
(
const
Vector2
&
v
)
const
{
return
x
!=
v
.
x
||
y
!=
v
.
y
;
}
private:
private:
float
x
,
y
;
float
x
,
y
;
};
};
...
@@ -55,6 +62,11 @@ int operator+(const C2 &, const C2 &) { return 22; }
...
@@ -55,6 +62,11 @@ int operator+(const C2 &, const C2 &) { return 22; }
int
operator
+
(
const
C2
&
,
const
C1
&
)
{
return
21
;
}
int
operator
+
(
const
C2
&
,
const
C1
&
)
{
return
21
;
}
int
operator
+
(
const
C1
&
,
const
C2
&
)
{
return
12
;
}
int
operator
+
(
const
C1
&
,
const
C2
&
)
{
return
12
;
}
// Note: Specializing explicit within `namespace std { ... }` is done due to a
// bug in GCC<7. If you are supporting compilers later than this, consider
// specializing `using template<> struct std::hash<...>` in the global
// namespace instead, per this recommendation:
// https://en.cppreference.com/w/cpp/language/extending_std#Adding_template_specializations
namespace
std
{
namespace
std
{
template
<
>
template
<
>
struct
hash
<
Vector2
>
{
struct
hash
<
Vector2
>
{
...
@@ -63,6 +75,11 @@ namespace std {
...
@@ -63,6 +75,11 @@ namespace std {
};
};
}
}
// Not a good abs function, but easy to test.
std
::
string
abs
(
const
Vector2
&
)
{
return
"abs(Vector2)"
;
}
// MSVC warns about unknown pragmas, and warnings are errors.
// MSVC warns about unknown pragmas, and warnings are errors.
#ifndef _MSC_VER
#ifndef _MSC_VER
#pragma GCC diagnostic push
#pragma GCC diagnostic push
...
@@ -107,7 +124,13 @@ TEST_SUBMODULE(operators, m) {
...
@@ -107,7 +124,13 @@ TEST_SUBMODULE(operators, m) {
.
def
(
float
()
/
py
::
self
)
.
def
(
float
()
/
py
::
self
)
.
def
(
-
py
::
self
)
.
def
(
-
py
::
self
)
.
def
(
"__str__"
,
&
Vector2
::
toString
)
.
def
(
"__str__"
,
&
Vector2
::
toString
)
.
def
(
hash
(
py
::
self
))
.
def
(
"__repr__"
,
&
Vector2
::
toString
)
.
def
(
py
::
self
==
py
::
self
)
.
def
(
py
::
self
!=
py
::
self
)
.
def
(
py
::
hash
(
py
::
self
))
// N.B. See warning about usage of `py::detail::abs(py::self)` in
// `operators.h`.
.
def
(
"__abs__"
,
[](
const
Vector2
&
v
)
{
return
abs
(
v
);
})
;
;
m
.
attr
(
"Vector"
)
=
m
.
attr
(
"Vector2"
);
m
.
attr
(
"Vector"
)
=
m
.
attr
(
"Vector2"
);
...
...
tests/test_operator_overloading.py
View file @
4e3d9fea
...
@@ -6,6 +6,9 @@ from pybind11_tests import ConstructorStats
...
@@ -6,6 +6,9 @@ from pybind11_tests import ConstructorStats
def
test_operator_overloading
():
def
test_operator_overloading
():
v1
=
m
.
Vector2
(
1
,
2
)
v1
=
m
.
Vector2
(
1
,
2
)
v2
=
m
.
Vector
(
3
,
-
1
)
v2
=
m
.
Vector
(
3
,
-
1
)
v3
=
m
.
Vector2
(
1
,
2
)
# Same value as v1, but different instance.
assert
v1
is
not
v3
assert
str
(
v1
)
==
"[1.000000, 2.000000]"
assert
str
(
v1
)
==
"[1.000000, 2.000000]"
assert
str
(
v2
)
==
"[3.000000, -1.000000]"
assert
str
(
v2
)
==
"[3.000000, -1.000000]"
...
@@ -24,7 +27,11 @@ def test_operator_overloading():
...
@@ -24,7 +27,11 @@ def test_operator_overloading():
assert
str
(
v1
*
v2
)
==
"[3.000000, -2.000000]"
assert
str
(
v1
*
v2
)
==
"[3.000000, -2.000000]"
assert
str
(
v2
/
v1
)
==
"[3.000000, -0.500000]"
assert
str
(
v2
/
v1
)
==
"[3.000000, -0.500000]"
assert
v1
==
v3
assert
v1
!=
v2
assert
hash
(
v1
)
==
4
assert
hash
(
v1
)
==
4
# TODO(eric.cousineau): Make this work.
# assert abs(v1) == "abs(Vector2)"
v1
+=
2
*
v2
v1
+=
2
*
v2
assert
str
(
v1
)
==
"[7.000000, 0.000000]"
assert
str
(
v1
)
==
"[7.000000, 0.000000]"
...
@@ -40,14 +47,17 @@ def test_operator_overloading():
...
@@ -40,14 +47,17 @@ def test_operator_overloading():
assert
str
(
v2
)
==
"[2.000000, 8.000000]"
assert
str
(
v2
)
==
"[2.000000, 8.000000]"
cstats
=
ConstructorStats
.
get
(
m
.
Vector2
)
cstats
=
ConstructorStats
.
get
(
m
.
Vector2
)
assert
cstats
.
alive
()
==
2
assert
cstats
.
alive
()
==
3
del
v1
del
v1
assert
cstats
.
alive
()
==
1
assert
cstats
.
alive
()
==
2
del
v2
del
v2
assert
cstats
.
alive
()
==
1
del
v3
assert
cstats
.
alive
()
==
0
assert
cstats
.
alive
()
==
0
assert
cstats
.
values
()
==
[
assert
cstats
.
values
()
==
[
'[1.000000, 2.000000]'
,
'[1.000000, 2.000000]'
,
'[3.000000, -1.000000]'
,
'[3.000000, -1.000000]'
,
'[1.000000, 2.000000]'
,
'[-3.000000, 1.000000]'
,
'[-3.000000, 1.000000]'
,
'[4.000000, 1.000000]'
,
'[4.000000, 1.000000]'
,
'[-2.000000, 3.000000]'
,
'[-2.000000, 3.000000]'
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment