Opened 7 years ago

Closed 7 years ago

#11826 closed Bugs (fixed)

float128.hpp: too aggressive NOTHROW on converting assignment operator

Reported by: martin.seemann@… Owned by: John Maddock
Milestone: To Be Determined Component: multiprecision
Version: Boost Development Trunk Severity: Regression
Keywords: float128 nothrow Cc:

Description

In order to fix another issue, commit https://github.com/boostorg/multiprecision/commit/9927d49cb9d87c022c3ac49b3c8d84ce55ab7dc4 introduced several unconditional BOOST_NOTHROWs in float128.hpp. In my opinion, at least some of them are problematic, especially for the assignment operator (line 150) and the conversion constructor (line 147). Both support initialization from any type implicitly convertible to the underlying float128_type. However, implicit conversion routines might throw, as demonstrated by the following example program:

// g++ -std=c++11 exception_float128.cpp -o exception_float128 -fext-numeric-literals -lquadmath
#include <iostream>
#include <stdexcept>
#include <boost/multiprecision/float128.hpp>

struct outer {
	template <typename T> struct inner {
		T operator()() const {
			throw std::runtime_error("Bad stuff happened");
			return T{0};
		}
	};
	
	template <typename Target, typename = typename std::enable_if<!std::is_same<Target, const char *>::value>::type> operator Target() const {
		return inner<Target>()();
	}
};

int main() {
	boost::multiprecision::float128 destination;	
	outer source;
	try {		
		destination = source;
	} catch (const std::exception &e) {
		std::cerr << "caught exception: " << e.what() << "\n";
	}
	return 0;
}

Compiled with recent boost, this code std::terminate's. If BOOST_NOTHROW in float128.hpp:150 is replaced by BOOST_NOEXCEPT_IF(noexcept(std::declval<float128_type&>() = std::declval<const T&>())), the exception is caught as expected. Such conditional noexcept specifiers might be required in some more places, provided there isn't a policy that I am unaware of, which forbids implicit conversion operators to throw.

(BTW: the above code is not just a twisted mockup. I hit the problem while developing a conversion library that uses the "template <typename T> operator T()" trick to let the compiler deduce the target type automatically. An appropriate functor is then selected that implements the actual conversion or throws, if no suitable source data is provided.)

Change History (1)

comment:1 by John Maddock, 7 years ago

Resolution: fixed
Status: newclosed
Note: See TracTickets for help on using tickets.