Boost logo

Boost :

From: Giovanni Piero Deretta (gpderetta_at_[hidden])
Date: 2008-07-02 19:04:05


On Thu, Jul 3, 2008 at 12:06 AM, David Abrahams <dave_at_[hidden]> wrote:
> Giovanni Piero Deretta wrote:
>> On Wed, Jul 2, 2008 at 8:40 PM, Eric Niebler <eric_at_[hidden]> wrote:
>
>>> I don't know a sufficiently portable way to ask a type whether it has
>>> implemented the result_of protocol. In C++0x, result_of will simply use
>>> decltype, so at the very least Phoenix's approach is forward-compatible.
>>>
>>
>> With 'portable' you mean 'works with non completely compliant compilers'?
>> Otherwise I think you can legally sfinae on the presence of both
>> result<> and result_type.
>
> Demonstration, please. I don't know of a way to detect a nested
> template with SFINAE.
>

Daniel Walker posted a patch sometime ago to add
BOOST_HAS_TEMPLATE_XXX to mpl. Here is a link:

  http://svn.boost.org/trac/boost/ticket/861

I'm sure that Eric is aware of it (and you too actually :) ) but IIRC
he feared the amount of compiler workarounds.
I use a variant of this to dinstinguish between 'sig' and 'result' and
work fairly well on gcc 3.3 and 4.x.
Here is a short test:

#include <boost/static_assert.hpp>

typedef char true_type[2];
typedef char false_type[1];

false_type& test(...);

template<class T, class T2>
struct dummy{};

template<class T1, class T2>
true_type& test(dummy<T1, T2>, typename T1:: template result<T2>* =0);

struct foo {};
struct bar { template<typename T> struct result{}; };
struct baz { int result; };
struct barf { typedef int result; };
struct bas { template<class T1, class T2> struct result{} ; };
struct bax { template<class T1, class T2=void> struct result{} ; };

BOOST_STATIC_ASSERT(sizeof(test(dummy<foo, int()>())) == sizeof(false_type));
BOOST_STATIC_ASSERT(sizeof(test(dummy<bar, int()>())) == sizeof(true_type));
BOOST_STATIC_ASSERT(sizeof(test(dummy<baz, int()>())) == sizeof(false_type));
BOOST_STATIC_ASSERT(sizeof(test(dummy<barf, int()>())) == sizeof(false_type));
//BOOST_STATIC_ASSERT(sizeof(test(dummy<bas, int()>())) == sizeof(false_type));
BOOST_STATIC_ASSERT(sizeof(test(dummy<bax, int()>())) == sizeof(true_type));

Unfortunately it fails (with a compiler error, not with a misleading
detection) if a class has a nested result with more than one (non
defaulted) argument.
I think that Daniel Walker found some tricks plus compier workarounds
to overcome this problem for the general MPL_HAS_TEMPLATE_XXX,
But even with the plain test, it is not a big stretch to assume that a
function object will not have result<> nested
template unless it is trying to implement the result protocol.

HTH,

-- 
gpd

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk