[multiprecision] [detail] [number_base.hpp] Ambiguous partial specialization for canonical_imp
It looks like boost/multiprecision/detail/number_base.hpp header in one of the later trunk versions has ambiguous partial specialization problem which Oracle Studio 12.4 C++ compiler detects. It can be also detected by gcc-4.8.2 as small 35 lines independent test case below made from this header shows. gcc -c -std=c++11 t.cc # gcc-4.8.2 compilation t.cc:17:62: error: ambiguous class template instantiation for 'struct canonical_imp<number<cpp_dec_float<50u>, (expression_template_option)1u>, cpp_dec_float<50u>, int_<3> >' CC -c -std=c++11 t.cc # Oracle Studio 12.4 C++ compilation "t.cc", line 17: Error: Ambiguous partial specialization for canonical_imp<Val, Backend, Tag><number<cpp_dec_float<50, int, void>, 1>, cpp_dec_float<50, int, void>, int_<3>>, canonical_imp<Val, Backend, int_<3>> and canonical_imp<number<B, 1>, Backend, Tag>. t.cc ================================== template< bool B> struct enable_if_c{ typedef bool type; }; template< int N > struct int_{}; enum expression_template_option {et_on=1}; template <class Backend, expression_template_option ExpressionTemplates> class number; template <class Val, class Backend, class Tag> struct canonical_imp { typedef int type; }; template <class B,class Backend,class Tag> struct canonical_imp<number<B,et_on>,Backend,Tag> { typedef B type; }; template <class Val, class Backend> struct canonical_imp<Val,Backend,int_<3>>{ typedef Val type; }; template <class Val, class Backend> struct canonical { typedef typename canonical_imp<Val, Backend, int_<3>>::type type; }; template<typename From, typename To> struct is_restricted_conversion { typedef bool type; }; template <class Backend, expression_template_option ExpressionTemplates> class number { public: number() {} template <class V> number(const V& v,typename enable_if_c<!is_restricted_conversion<typename canonical<V,Backend>::type,Backend>::value>::type * =0){} }; template <unsigned Digits10, class ExponentType = int, class Allocator = void> class cpp_dec_float; template <unsigned Digits10, class ExponentType, class Allocator> class cpp_dec_float { public: cpp_dec_float() {} }; template <class RealType> void instantiate(RealType) {} typedef number<cpp_dec_float<50>, et_on> test_type; void foo() { instantiate(test_type()); } =============================== Any suggestions how to fix this? Thanks, Sergey
It looks like boost/multiprecision/detail/number_base.hpp header in one of the later trunk versions has ambiguous partial specialization problem which Oracle Studio 12.4 C++ compiler detects. It can be also detected by gcc-4.8.2 as small 35 lines independent test case below made from this header shows.
gcc -c -std=c++11 t.cc # gcc-4.8.2 compilation t.cc:17:62: error: ambiguous class template instantiation for 'struct canonical_imp<number<cpp_dec_float<50u>, (expression_template_option)1u>, cpp_dec_float<50u>, int_<3> >'
Going back to the original code rather than the reduced case, the final int_<3> implies that the first template argument (number<cpp_dec_float<50u> in this case) is convertible to const char* - and that should definitely *not* be the case. To put it another way, the error message could be a lot better (maybe I'll add a static assert for this special case), but the ambiguity is justified because: is_convertible<number<cpp_dec_float<50u> >, const char*>::value should never be true, and if it is, the code genuinely doesn't know what to do. So is there a compiler bug effecting is_convertible? Do the type_traits tests pass? Merry Christmas, John. P.S. we will have to figure out a Boost.Config setup for this new compiler release as well - really great that Sun have revitalised their compiler with C++11 support.
On 12/28/14 04:09, John Maddock wrote:
Going back to the original code rather than the reduced case, the final int_<3> implies that the first template argument (number<cpp_dec_float<50u> in this case) is convertible to const char* - and that should definitely *not* be the case. To put it another way, the error message could be a lot better (maybe I'll add a static assert for this special case), but the ambiguity is justified because:
is_convertible<number<cpp_dec_float<50u> >, const char*>::value
should never be true, and if it is, the code genuinely doesn't know what to do. So is there a compiler bug effecting is_convertible? Do the type_traits tests pass?
Thank you John, You got it right, and indeed there is compiler bug for libs/type_traits/test/is_convertible_test.cpp As I may see from type_traits logfile that test got 3 separate run-time miscompares: is_convertible_test.cpp:113: The expression: "(::boost::is_convertible<const int *, int*>::value)" had an invalid value (found 1, expected 0) is_convertible_test.cpp:114: The expression: "(::boost::is_convertible<const int&, int&>::value)" had an invalid value (found 1, expected 0) is_convertible_test.cpp:131: The expression: "(::boost::is_convertible<const int[2], int*>::value)" had an invalid value (found 1, expected 0) I cooked 90 lines independent executable test case for those miscomares, and our c++ developers quickly reduced it to 10 lines executable. So, hopefully the problem will be fixed soon. But could you also clarify one more thing for me. Assuming that problem will be fixed, and is_convertible will start to work properly, how that will affect and original issue? Or put in another way, do you think that code below from libs/multiprecision/test/test_mixed_float.cpp is correct? int main() { using namespace boost::multiprecision; test<cpp_dec_float_50, cpp_dec_float_100>(); ... And if this is the case, then how in you opinion compiler should deal with it? Thanks, Sergey
participants (2)
-
John Maddock
-
Sergey Sprogis