-
-
Save afabri/acc723427888dc49c60099bdb6220c53 to your computer and use it in GitHub Desktop.
#include <boost/operators.hpp> | |
#include <boost/multiprecision/cpp_int.hpp> | |
#include <Eigen/Dense> | |
// Quotient | |
template <class NT_> | |
class Toto | |
: boost::additive2 < Toto<NT_>, NT_ > | |
{ | |
public: | |
NT_ num, den; | |
Toto() {} | |
Toto(const NT_& a) {} | |
Toto(const NT_& a, const NT_&b) {} | |
template <class T> | |
Toto operator+=(const T&) { return *this; } | |
}; | |
// Sqrt_extension: | |
template <class NT_> | |
class Toto2 | |
: boost::additive2 < Toto2<NT_>, NT_ > | |
{ | |
public: | |
NT_ num, den; | |
Toto2() {} | |
Toto2(const NT_& nt) | |
{} | |
template <class T> | |
Toto2 operator+=(const T&) { return *this; } | |
}; | |
void toto(Toto<boost::multiprecision::cpp_int>& x) | |
{ | |
x.den; | |
} | |
// No idea if needed | |
namespace Eigen { | |
template<class> struct NumTraits; | |
template<class NT> struct NumTraits<Toto<NT> > | |
{ | |
typedef Toto<NT> Real; | |
typedef Toto<NT> NonInteger; | |
typedef Toto<NT> Nested; | |
typedef Toto<NT> Literal; | |
static inline Real epsilon() { return NumTraits<NT>::epsilon(); } | |
static inline Real dummy_precision() { return NumTraits<NT>::dummy_precision(); } | |
enum { | |
IsInteger = 0, | |
IsSigned = 1, | |
IsComplex = 0, | |
RequireInitialization = NumTraits<NT>::RequireInitialization, | |
ReadCost = 2 * NumTraits<NT>::ReadCost, | |
AddCost = 150, | |
MulCost = 100 | |
}; | |
}; | |
template<class NT> struct NumTraits<Toto2<NT> > | |
{ | |
typedef Toto2<NT> Real; | |
typedef Toto2<NT> NonInteger; | |
typedef Toto2<NT> Nested; | |
typedef Toto2<NT> Literal; | |
static inline Real epsilon() { return NumTraits<NT>::epsilon(); } | |
static inline Real dummy_precision() { return NumTraits<NT>::dummy_precision(); } | |
enum { | |
IsInteger = 0, | |
IsSigned = 1, | |
IsComplex = 0, | |
RequireInitialization = NumTraits<NT>::RequireInitialization, | |
ReadCost = 2 * NumTraits<NT>::ReadCost, | |
AddCost = 150, | |
MulCost = 100 | |
}; | |
}; | |
} | |
int main() { | |
typedef Toto2<int> NT; | |
Eigen::Matrix<NT, 3, 3> m(3, 3); | |
m + m; | |
return 0; | |
} |
And let me share the error message. As far as I understand tries to find out if one can construct a cpp_int
from a Matrix
.
Build started...
1>------ Build started: Project: minimalVC2017, Configuration: Debug x64 ------
1>minimalVC2017.cpp
1>C:\local\boost_1_74_0\boost/multiprecision/traits/is_byte_container.hpp(22,97): error C2039: 'value_type': is not a member of 'std::iterator_traits<void>'
1>C:\local\boost_1_74_0\boost/multiprecision/traits/is_byte_container.hpp(22,52): message : see declaration of 'std::iterator_traits<void>'
1>C:\local\boost_1_74_0\boost/multiprecision/traits/is_byte_container.hpp(32): message : see reference to class template instantiation 'boost::multiprecision::detail::is_byte_container_imp<C,true>' being compiled
1> with
1> [
1> C=Eigen::Matrix<NT,3,3,0,3,3>
1> ]
1>C:\local\boost_1_74_0\boost/type_traits/is_convertible.hpp(490): message : see reference to class template instantiation 'boost::multiprecision::detail::is_byte_container<From>' being compiled
1> with
1> [
1> From=Eigen::Matrix<NT,3,3,0,3,3>
1> ]
1>C:\local\boost_1_74_0\boost/multiprecision/cpp_int.hpp(2074,4): message : while compiling class template member function 'boost::multiprecision::backends::cpp_int_backend<0,0,boost::multiprecision::signed_magnitude,boost::multiprecision::unchecked,std::allocator<boost::multiprecision::limb_type>>::cpp_int_backend(const Container &,const boost::enable_if_c<boost::multiprecision::detail::is_byte_container<Arithmetic>::value,void>::type *)'
1>C:\GitHub\cgal\Number_types\test\Number_types\minimalVC2017.cpp(97,10): message : see reference to class template instantiation 'boost::is_convertible<Eigen::Matrix<NT,3,3,0,3,3>,Backend>' being compiled
1> with
1> [
1> Backend=boost::multiprecision::backends::cpp_int_backend<0,0,boost::multiprecision::signed_magnitude,boost::multiprecision::unchecked,std::allocator<boost::multiprecision::limb_type>>
1> ]
1>C:\local\boost_1_74_0\boost/multiprecision/number.hpp(68,4): message : while compiling class template member function 'boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0,0,boost::multiprecision::signed_magnitude,boost::multiprecision::unchecked,std::allocator<boost::multiprecision::limb_type>>,boost::multiprecision::et_on>::number(const V &,boost::enable_if_c<boost::is_convertible<detail::canonical<V,Backend>::type,Backend>::value&&!boost::multiprecision::detail::is_restricted_conversion<detail::canonical<V,Backend>::type,Backend>::value,void>::type *) noexcept(<expr>)'
1> with
1> [
1> Backend=boost::multiprecision::backends::cpp_int_backend<0,0,boost::multiprecision::signed_magnitude,boost::multiprecision::unchecked,std::allocator<boost::multiprecision::limb_type>>
1> ]
1>C:\local\boost_1_74_0\boost/multiprecision/traits/is_byte_container.hpp(22,1): error C2146: syntax error: missing '>' before identifier 'value_type'
1>C:\local\boost_1_74_0\boost/multiprecision/traits/is_byte_container.hpp(22,1): error C2062: type 'unknown-type' unexpected
1>C:\local\boost_1_74_0\boost/multiprecision/traits/is_byte_container.hpp(22,110): error C2039: 'type': is not a member of '`global namespace''
1>C:\local\boost_1_74_0\boost/multiprecision/traits/is_byte_container.hpp(22,1): error C2238: unexpected token(s) preceding ';'
1>C:\local\boost_1_74_0\boost/multiprecision/traits/is_byte_container.hpp(23,142): error C2065: 'container_value_type': undeclared identifier
1>C:\local\boost_1_74_0\boost/multiprecision/traits/is_byte_container.hpp(23,130): error C2923: 'boost::is_integral': 'container_value_type' is not a valid template type argument for parameter 'T'
1>C:\local\boost_1_74_0\boost/multiprecision/traits/is_byte_container.hpp(23,142): message : see declaration of 'container_value_type'
1>C:\local\boost_1_74_0\boost/multiprecision/traits/is_byte_container.hpp(23,165): error C2955: 'boost::is_integral': use of class template requires template argument list
1>C:\local\boost_1_74_0\boost/type_traits/is_integral.hpp(22,39): message : see declaration of 'boost::is_integral'
1>C:\local\boost_1_74_0\boost/multiprecision/traits/is_byte_container.hpp(23,182): error C2065: 'container_value_type': undeclared identifier
1>Done building project "minimalVC2017.vcxproj" -- FAILED.
I'm fairly sure I remember fixing something around this area, can you please try a more up to date Boost version?
BTW I've tried to reproduce this locally, but failed so far.
With boost 1.79 it works. We would like to also support older boost versions for CGAL users.
BTW I've tried to reproduce this locally, but failed so far.
What version of boost did you use?
I tried several going back to 1.73.
I can reproduce the same errors as @afabri with Boost 1.74, Eigen 3.4 and MSVC 2017.
For consitency of our tests, here is the CMakeLists I am using
cmake_minimum_required(VERSION 3.1...3.23)
project(Number_types_Tests)
find_package(Boost 1.74 REQUIRED)
find_package(Eigen3 3.2.0 REQUIRED)
add_executable(boost-mp-operator-eigen-VC2017bug "boost-mp-operator-eigen-VC2017bug.cpp" )
target_link_libraries(boost-mp-operator-eigen-VC2017bug PUBLIC Eigen3::Eigen)
target_link_libraries(boost-mp-operator-eigen-VC2017bug PUBLIC Boost::boost)
In my tests, the example does not compile with
- Eigen 3.4 and master version
- MSVC 2017, 2019 and 2022 compilers
- boost 1.74
It does compile when I switch to boost 1.80
@sloriot had suggested to git bisect on boost::mp
@jzmaddock could it be a hacky fix to add a specialization of is_byte_container
for Eigen::Matrix
?
typedef Eigen::Matrix<NT, 3, 3>::const_iterator It;
std::cout << typeid(It).name() << std::endl;
The output is void
.
Adding this solves my problem above:
namespace boost {
namespace multiprecision {
namespace detail {
template <class A, int B, int C, int D, int E, int F>
struct is_byte_container< Eigen::Matrix<A,B,C,D,E,F>>
{
static const bool value = false;
};
} } }
In the real code I would also need a specialization for Ref<Eigen::Matrix<..>,..>
, and maybe even more :<
could it be a hacky fix to add a specialization of is_byte_container for Eigen::Matrix ?
It that fixes things, then I don't see why not - it would have to be to your code as a workaround, and you could predicate it on BOOST_VERSION should you wish - that would also protect you from any future changes to is_byte_container
given that it's an implementation detail (not that I'm planning to change it, but you know, 12 months from now I'll probably have forgotten this conversation!).
I added these specializations in CGAL/config.h
See also the pull request #6035
In fact in the testsuite it does not compile with VC2017. I maybe oversimplified because I just realized that this gist also does not compile with VC2022 (but with clang).
Also a hint: When I comment line 43 it compiles.