hastri
hastri

Reputation: 81

Strange boost cpp_Int behaviour when using auto type deduction

I just noticed some really strange behaviour when using auto to store the result of a boost cpp_int operation

#include <boost/multiprecision/cpp_int.hpp>

int main() {
    using boost::multiprecision::cpp_int;
    cpp_int a = 1, b = 10 * a, d;
    auto c = 10 * a;
    d = c;
    std::cout << b << " " << c << " " << d << "\n";
}

which outputs:

10 0 0 

instead of:

10 10 10

can anybody explain this?

Upvotes: 3

Views: 105

Answers (1)

Praetorian
Praetorian

Reputation: 109219

The problem is that boost::multiprecision uses expression templates in an attempt to avoid computing intermediate results (the linked Boost page has a section explaining the reasons for doing so).

Because of that, the type of c in the following expression is not cpp_int

auto c = 10 * a;  // c is some internal implementation defined type

You can confirm this by comparing the types of say a and c.

#include <boost/type_index.hpp>
std::cout << boost::typeindex::type_id_with_cvr<decltype(c)>().pretty_name();

The Boost introduction even specifically mentions the pitfall of using auto to store an expression template

One other potential pitfall that's only possible in C++11: you should never store an expression template using:

 auto my_expression = a + b - c;

unless you're absolutely sure that the lifetimes of a, b and c will outlive that of my_expression.

In your case, one of the operands is a literal, which seems to affect the result of converting the expression template to cpp_int even though the lifetime of c matches that of a. What happens exactly is difficult to say without delving deeper into the implementation of operator*, but suffice to say that you're doing something you shouldn't be, and most likely your example has undefined behavior.

You can fix the problem in several ways, beginning with use cpp_int instead of auto. Or cast the result of the expression template to cpp_int.

auto c = cpp_int(10 * a);

Or store the 10 in a cpp_int; then the caveat mentioned in the Boost documentation applies, and your example produces the expected result.

cpp_int a = 1, b = 10 * a, d, e = 10;
auto c = e * a;

Upvotes: 1

Related Questions