#include <type_traits>
template<typename U, typename L>
static auto Update(volatile U &state, const L &lambda) ->
//typename std::result_of<L(U,U)>::type
decltype(lambda(*(U*)0,*(U*)0))
{
typedef decltype(lambda(*(U*)0,*(U*)0)) ResultType;
//typedef typename std::result_of<L(U,U)>::type ResultType;
return Update<ResultType,U,L>(state, lambda, (typename std::is_void<ResultType>::type *)0);
}
// Specialization for lambda that returns type R (not void)
template<typename R, typename U, typename L>
static R Update(volatile U &state, const L &lambda, const std::false_type *)
{
// Real code does cmpxchg loop
return state;
}
template<typename R, typename U, typename L>
static void Update(volatile U &state, const L &lambda, const std::true_type *)
{
// Real code does cmpxchg loop
}
int main()
{
int x;
auto shouldBeBool = Update(x,
[](int oldvalue, int &newvalue)
{
newvalue = oldvalue + 1;
return true;
});
return (int)std::is_same<bool,decltype(shouldBeBool)>::value;
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgoKdGVtcGxhdGU8dHlwZW5hbWUgVSwgdHlwZW5hbWUgTD4KICBzdGF0aWMgYXV0byBVcGRhdGUodm9sYXRpbGUgVSAmc3RhdGUsIGNvbnN0IEwgJmxhbWJkYSkgLT4KICAgICAgLy90eXBlbmFtZSBzdGQ6OnJlc3VsdF9vZjxMKFUsVSk+Ojp0eXBlCiAgICAgIGRlY2x0eXBlKGxhbWJkYSgqKFUqKTAsKihVKikwKSkKICB7CiAgICB0eXBlZGVmIGRlY2x0eXBlKGxhbWJkYSgqKFUqKTAsKihVKikwKSkgUmVzdWx0VHlwZTsKICAgIC8vdHlwZWRlZiB0eXBlbmFtZSBzdGQ6OnJlc3VsdF9vZjxMKFUsVSk+Ojp0eXBlIFJlc3VsdFR5cGU7CgogICAgcmV0dXJuIFVwZGF0ZTxSZXN1bHRUeXBlLFUsTD4oc3RhdGUsIGxhbWJkYSwgKHR5cGVuYW1lIHN0ZDo6aXNfdm9pZDxSZXN1bHRUeXBlPjo6dHlwZSAqKTApOwogIH0KCiAgLy8gU3BlY2lhbGl6YXRpb24gZm9yIGxhbWJkYSB0aGF0IHJldHVybnMgdHlwZSBSIChub3Qgdm9pZCkKICB0ZW1wbGF0ZTx0eXBlbmFtZSBSLCB0eXBlbmFtZSBVLCB0eXBlbmFtZSBMPgogIHN0YXRpYyBSIFVwZGF0ZSh2b2xhdGlsZSBVICZzdGF0ZSwgY29uc3QgTCAmbGFtYmRhLCBjb25zdCBzdGQ6OmZhbHNlX3R5cGUgKikKICB7CiAgICAgIC8vIFJlYWwgY29kZSBkb2VzIGNtcHhjaGcgbG9vcAogICAgICByZXR1cm4gc3RhdGU7CiAgfQoKICB0ZW1wbGF0ZTx0eXBlbmFtZSBSLCB0eXBlbmFtZSBVLCB0eXBlbmFtZSBMPgogIHN0YXRpYyB2b2lkIFVwZGF0ZSh2b2xhdGlsZSBVICZzdGF0ZSwgY29uc3QgTCAmbGFtYmRhLCBjb25zdCBzdGQ6OnRydWVfdHlwZSAqKQogIHsKICAgICAgLy8gUmVhbCBjb2RlIGRvZXMgY21weGNoZyBsb29wCiAgfQogIAppbnQgbWFpbigpCnsKICBpbnQgeDsKICBhdXRvIHNob3VsZEJlQm9vbCA9IFVwZGF0ZSh4LAogIFtdKGludCBvbGR2YWx1ZSwgaW50ICZuZXd2YWx1ZSkKICB7CiAgICBuZXd2YWx1ZSA9IG9sZHZhbHVlICsgMTsKICAgIHJldHVybiB0cnVlOwogIH0pOwogIAogIHJldHVybiAoaW50KXN0ZDo6aXNfc2FtZTxib29sLGRlY2x0eXBlKHNob3VsZEJlQm9vbCk+Ojp2YWx1ZTsKfQo=