/*** * * Test program to illustrate the problem: * * "Phoenix function with reference parameter fails to compile under clang 3.5 with C++ 11 support" * * Author: David Williams * * Boost version: 1.59 * * Compiler: Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn) * * Program built using C++ 11 support. * * Test program based on the phoenix test program function_tests.cpp. * ***/ #include #include #include #include #include #include #define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS #include #undef BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS /** * Defines a simple phoenix function that allows a flag to be set depending on the integer * value used to initiaise the object. * **/ struct add_int_impl { typedef int result_type; add_int_impl(int v) { _value=v; } /* * Need this defined for the call BOOST_TEST(add_int(arg1)(flag) == (4)); to compile when * the flags BOOST_RESULT_OF_TR1 or BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK are NOT used. * * Note that both operator functions must be const for them to be valid phoenix functions. * This function compiles OK both with and without the int operator()(bool& flag) being defined. */ /**** int operator()(int a) const { std::cout << "int operator()(int a) called" << std::endl; return a + _value; } ****/ /* * This can be compiled with no other overloaded operators if we define the param as * (const bool& flag) rather than just (bool& flag) * But a const reference paramter is not useful here as we want to change the flag * depending on the stored integer _value. * */ int operator()(bool& flag) const { std::cout << "int operator()(bool& flag) called" << std::endl; if (_value == 4) flag=true; return _value; } int _value; }; // Initialise the function with the value 4. boost::phoenix::function add_int(4); int main() { using boost::phoenix::arg_names::arg1; int i5 = 5; bool flag=false; /** * Test invoking the function object with a bool flag as a reference parameter. * * This call will only compile under Apple's version of clang 3.5 C++ 11 when one or both of the * following conditions are met; * * 1) The int operator()(int a) const is also defined * * 2) One of the following flags is defined: * * BOOST_RESULT_OF_TR1 * BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK * * The program also compiles if the function signature is changed to use a const * reference parameter, i.e int operator()(const bool& flag) const. * However this then means that the parameter value cannot be * modified within the body of the function as required. * * The problem does not occur if the program is compiled using C++ 98 compatibility mode. * **/ BOOST_TEST(add_int(arg1)(flag) == (4)); /** * This tests the int operator()(int a) const which under C++ 11 can be defined standalone or * with the int operator()(bool& flag) const also defined. The flags BOOST_RESULT_OF_TR1 * and BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK are then NOT required. */ //BOOST_TEST(add_int(arg1)(i5) == (5+4)); return boost::report_errors(); }