我想创建可与 mp-units 一起使用的自定义 Vector 类,但我无法创建
operator*()
和 `operator*()。我在 godbolt 上重现了问题:https://godbolt.org/z/sMbxccMev 这里是有问题的代码:
#include "units/isq/si/length.h"
#include "units/isq/si/area.h"
#include "units/math.h"
#include <iostream>
template<units::Quantity quantity>
struct Vector
{
quantity x;
quantity y;
Vector& operator+=(const Vector& rhs)
{
x += rhs.x;
y += rhs.y;
return *this;
}
friend Vector operator+(Vector lhs,
const Vector& rhs)
{
lhs += rhs;
return lhs;
}
Vector& operator-=(const Vector& rhs)
{
x -= rhs.x;
y -= rhs.y;
return *this;
}
friend Vector operator-(Vector lhs,
const Vector& rhs)
{
lhs -= rhs;
return lhs;
}
[[nodiscard]] Vector<units::dimensionless<units::one>> normalized() const
{
return {x/norm(),y/norm()};
}
[[nodiscard]] decltype(std::declval<quantity>()*std::declval<quantity>()) norm_squared() const
{
return x * x + y * y;
}
[[nodiscard]] quantity norm() const
{
return units::sqrt(norm_squared());
}
[[nodiscard]] quantity distanceTo(const Vector& other) const
{
return (other - *this).norm();
}
};
template<units::Quantity vector_quantity, typename S>
auto operator*(Vector<vector_quantity> lhs, const S& rhs)
{
auto tmp_x = lhs.x * rhs;
auto tmp_y = lhs.y * rhs;
return Vector{tmp_x,tmp_y};
}
template<units::Quantity vector_quantity, typename scalar>
auto operator/(Vector<vector_quantity> lhs,
const scalar & rhs) -> Vector<decltype(std::declval<vector_quantity>()/std::declval<scalar>())>
{
Vector<decltype(std::declval<vector_quantity>()/std::declval<scalar>())> tmp;
tmp.x = lhs.x / rhs;
tmp.y = lhs.y / rhs;
return tmp;
}
int main()
{
using namespace units::isq::si::references;
auto some_val = 2 * m;
Vector<units::isq::si::length<units::isq::si::metre>> some_vector{2 * m, 2 * m};
auto other = some_vector.normalized(); // should be Vector<units::dimensionless<units::one>>
std::cout << std::boolalpha << std::is_same<decltype(other), Vector<units::dimensionless<units::one>>>::value;
auto another = other * some_val; // should be Vector<units::isq::si::length<units::isq::si::metre>> again
std::cout << std::boolalpha << std::is_same<decltype(another), Vector<units::isq::si::length<units::isq::si::metre>>>::value;
}
和错误信息:
In file included from /opt/compiler-explorer/libs/mp-units/v0.7.0/src/core/include/units/bits/external/hacks.h:81,
from /opt/compiler-explorer/libs/mp-units/v0.7.0/src/core/include/units/bits/basic_concepts.h:25,
from /opt/compiler-explorer/libs/mp-units/v0.7.0/src/core/include/units/concepts.h:26,
from /opt/compiler-explorer/libs/mp-units/v0.7.0/src/systems/isq/include/units/isq/dimensions/length.h:25,
from /opt/compiler-explorer/libs/mp-units/v0.7.0/src/systems/si/include/units/isq/si/length.h:26,
from <source>:1:
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/bits/stl_function.h: In substitution of 'template<class Value> requires !(Quantity<Value>) && (invoke_result_convertible_to_<Rep, std::multiplies<void>, const Value&, Rep>) constexpr auto [requires units::Quantity<<placeholder>, >] units::operator*(const Value&, const units::quantity<units::dim_one, units::one, double>&) [with Value = units::dim_one]':
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/bits/stl_function.h:281:37: required by substitution of 'template<class _Tp, class _Up> constexpr decltype ((forward<_Tp>(__t) * forward<_Up>(__u))) std::multiplies<void>::operator()(_Tp&&, _Up&&) const [with _Tp = const Vector<units::quantity<units::dim_one, units::one, double> >&; _Up = double]'
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/type_traits:2536:26: required by substitution of 'template<class _Fn, class ... _Args> static std::__result_of_success<decltype (declval<_Fn>()((declval<_Args>)()...)), std::__invoke_other> std::__result_of_other_impl::_S_test(int) [with _Fn = std::multiplies<void>; _Args = {const Vector<units::quantity<units::dim_one, units::one, double> >&, double}]'
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/type_traits:2547:55: required from 'struct std::__result_of_impl<false, false, std::multiplies<void>, const Vector<units::quantity<units::dim_one, units::one, double> >&, double>'
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/type_traits:2552:12: required from 'struct std::__invoke_result<std::multiplies<void>, const Vector<units::quantity<units::dim_one, units::one, double> >&, double>'
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/type_traits:3013:12: [ skipping 4 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/type_traits:2536:26: required by substitution of 'template<class _Fn, class ... _Args> static std::__result_of_success<decltype (declval<_Fn>()((declval<_Args>)()...)), std::__invoke_other> std::__result_of_other_impl::_S_test(int) [with _Fn = std::multiplies<void>; _Args = {const Vector<units::quantity<units::dim_one, units::one, double> >&, int}]'
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/type_traits:2547:55: required from 'struct std::__result_of_impl<false, false, std::multiplies<void>, const Vector<units::quantity<units::dim_one, units::one, double> >&, int>'
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/type_traits:3013:12: recursively required by substitution of 'template<class _Result, class _Ret> struct std::__is_invocable_impl<_Result, _Ret, true, std::__void_t<typename _CTp::type> > [with _Result = std::__invoke_result<std::multiplies<void>, const Vector<units::quantity<units::dim_one, units::one, double> >&, int>; _Ret = void]'
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/type_traits:3013:12: required from 'struct std::is_invocable<std::multiplies<void>, const Vector<units::quantity<units::dim_one, units::one, double> >&, int>'
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/type_traits:3260:71: required from 'constexpr const bool std::is_invocable_v<std::multiplies<void>, const Vector<units::quantity<units::dim_one, units::one, double> >&, int>'
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/concepts:336:25: required by substitution of 'template<class Value> requires !(Quantity<Value>) && (invoke_result_convertible_to_<Rep, std::multiplies<void>, const Value&, Rep>) constexpr auto [requires units::Quantity<<placeholder>, >] units::operator*(const Value&, const units::quantity<units::isq::si::dim_length, units::isq::si::metre, int>&) [with Value = units::isq::si::dim_length]'
<source>:84:28: required from here
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/concepts:336:13: required for the satisfaction of 'invocable<_Fn, _Args ...>' [with _Fn = std::multiplies<void>; _Args = {const Vector<units::quantity<units::dim_one, units::one, double> >&, double}]
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/concepts:340:13: required for the satisfaction of 'regular_invocable<Func, T, U>' [with Func = std::multiplies<void>; U = double; T = const Vector<units::quantity<units::dim_one, units::one, double> >&]
/opt/compiler-explorer/libs/mp-units/v0.7.0/src/core/include/units/quantity.h:77:9: required for the satisfaction of 'quantity_value_for_<Func, U, V>' [with Func = std::multiplies<void>; U = const Vector<units::quantity<units::dim_one, units::one, double> >&; V = double]
/opt/compiler-explorer/libs/mp-units/v0.7.0/src/core/include/units/quantity.h:82:9: required for the satisfaction of 'invoke_result_convertible_to_<Rep, std::multiplies<void>, const Value&, Rep>' [with Value = Vector<units::quantity<units::dim_one, units::one, double> >; Rep = double]
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/concepts:336:25: error: satisfaction of atomic constraint 'is_invocable_v<_Fn, _Args ...> [with _Fn = std::multiplies<void>; _Args = {const Value&, Rep}]' depends on itself
336 | concept invocable = is_invocable_v<_Fn, _Args...>;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'
Internal compiler error: Error reporting routines re-entered.
0x178854d error_at(unsigned int, char const*, ...)
???:0
0x6be0a2 satisfaction_cache::get()
???:0
0x6c2a6a constraints_satisfied_p(tree_node*, tree_node*)
???:0
0x7f4597 fn_type_unification(tree_node*, tree_node*, tree_node*, tree_node* const*, unsigned int, tree_node*, unification_kind_t, int, conversion**, bool, bool)
???:0
0x6924f0 build_new_op(op_location_t const&, tree_code, int, tree_node*, tree_node*, tree_node*, tree_node**, int)
???:0
0x82b7ed build_x_binary_op(op_location_t const&, tree_code, tree_node*, tree_code, tree_node*, tree_code, tree_node**, int)
???:0
0x7da35d tsubst(tree_node*, tree_node*, int, tree_node*)
???:0
0x1793bf2 pp_format(pretty_printer*, text_info*)
???:0
0x1794240 pp_format_verbatim(pretty_printer*, text_info*)
???:0
0x1794321 pp_verbatim(pretty_printer*, char const*, ...)
???:0
0x17873bd diagnostic_report_diagnostic(diagnostic_context*, diagnostic_info*)
???:0
0x178854d error_at(unsigned int, char const*, ...)
???:0
0x6be0a2 satisfaction_cache::get()
???:0
0x6c2a6a constraints_satisfied_p(tree_node*, tree_node*)
???:0
0x7f4597 fn_type_unification(tree_node*, tree_node*, tree_node*, tree_node* const*, unsigned int, tree_node*, unification_kind_t, int, conversion**, bool, bool)
???:0
0x6924f0 build_new_op(op_location_t const&, tree_code, int, tree_node*, tree_node*, tree_node*, tree_node**, int)
???:0
0x82b7ed build_x_binary_op(op_location_t const&, tree_code, tree_node*, tree_code, tree_node*, tree_code, tree_node**, int)
???:0
0x7d9bb8 maybe_instantiate_noexcept(tree_node*, int)
???:0
0x6929d3 build_op_call(tree_node*, vec<tree_node*, va_gc, vl_embed>**, int)
???:0
0x8082c2 finish_call_expr(tree_node*, vec<tree_node*, va_gc, vl_embed>**, bool, bool, int)
???:0
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.
有趣的是
operator/()
曾经在不同版本的库(或者更确切地说是不同的包管理 - 以前是 FetchContent_Declare,现在是 Conan)上处理 msvc,但我无法确定确切的版本。 operator*()
尝试修复。