Opened 12 years ago

Closed 8 years ago

#5408 closed Bugs (wontfix)

fold(transform(.... )) gives erroneous result: dangling reference?

Reported by: joe@… Owned by: Joel de Guzman
Milestone: To Be Determined Component: fusion
Version: Boost 1.47.0 Severity: Problem
Keywords: Cc: joel@…

Description

The code below demonstrates a problem using fusion's transform on a fold view in conjunction with a phoenix functional. It produces the output:

Should be the same: 1 =? 4.59177e-41

it should produce

Should be the same: 1 =? 1

Thanks, Joe

#include <iostream>
#include <cmath>
#include <boost/detail/lightweight_test.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/fusion/container.hpp>
#include <boost/fusion/functional.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/fusion/include/fold.hpp>
#include <boost/fusion/include/transform.hpp>
#include <boost/type_traits.hpp>
#include <boost/mpl/assert.hpp>

using namespace boost::fusion;
using namespace boost::phoenix;

typedef float OutputType;

// A general error function, measuring the difference between two output patterns.
struct error_function3 {
	template <typename Outputs1, typename Outputs2>
	struct result
	{
		typedef OutputType type;
	};

	template <typename Outputs1, typename Outputs2>
	OutputType operator()(Outputs1& outputs1, Outputs2& outputs2) const
	{
		using boost::phoenix::arg_names::_1;
		using boost::phoenix::arg_names::_2;
		using boost::fusion::fold;
		using boost::fusion::transform;

		float bad_result = fold(transform(outputs1, outputs2, (_1 - _2) * (_1 - _2)), 0, _1 + _2);
		float good_result = fold(as_vector(transform(outputs1, outputs2, (_1 - _2) * (_1 - _2))), 0, _1 + _2);

		std::cout << "Should be the same: " << good_result << " =? " << bad_result << std::endl;
		return good_result;
	}
};

int main() {
	using boost::phoenix::arg_names::_1;
	using boost::phoenix::arg_names::_2;
	vector<OutputType, OutputType> o1 = make_vector(1., 2.);
	vector<OutputType, OutputType> o2 = make_vector(2., 3.);

	boost::phoenix::function<error_function3> const error;
	std::cout << error(_1, _2)(o1, o2) << std::endl;
}

Change History (5)

comment:1 by anonymous, 12 years ago

Summary: transform(fold(.... )) gives erroneous result: dangling reference?fold(transform(.... )) gives erroneous result: dangling reference?

comment:2 by Joel de Guzman, 12 years ago

Cc: joel@… added

I suggest you use Phoenix-3 instead. It is in the Boost trunk. The problem here is that Phoenix-2 has a old and flaky result-type deduction scheme. Phoenix-3 is better. The changes required are minimal. First use the proper includes:

#include <boost/phoenix/core.hpp> #include <boost/phoenix/operator.hpp> #include <boost/phoenix/function.hpp>

Then, change the result-of of error_function3:

typedef OutputType result_type;

With the changes, I am getting:

Should be the same: 2 =? 2 2

comment:3 by joe@…, 12 years ago

Yes, that's fine! :) Now that I understand the changes to result_of I'm happy with moving to Pheonix 3.

comment:4 by Kohei Takahashi <flast@…>, 8 years ago

Phoenix V2 is already removed from release tarball. please close.

comment:5 by Joel de Guzman, 8 years ago

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