Boost logo

Boost :

Subject: Re: [boost] Workaround for compiler bugs
From: Edward Diener (eldiener_at_[hidden])
Date: 2010-12-08 00:10:30


On 12/6/2010 7:43 PM, Stephan T. Lavavej wrote:
> [Edward Diener]
>> You missed the fact in the attachment that the T passed in must be the
>> full signature of a pointer to data member, as in 'Gipf Dvonn::*' in
>> your first example below.
>
> I wasn't sure if mentioning the data member's type was a desired feature of your code. Here's how to achieve that:
>
> C:\Temp>type meow.cpp
> #include<type_traits>
>
> #define DEFINE_HAS_MEMBER_OF_TYPE(NAME) \
> template<typename T> class has_member_ ## NAME { \
> private: \
> template<typename U> static std::true_type helper(decltype(&U::NAME)); \

I quickly played around with this a little seeing if I could remove
'decltype'. Evidently the VC++ compiler can not handle:

"template<typename U> static std::true_type helper(&U::NAME);"

spitting out the message of

'error C2998: 'std::tr1::true_type helper' : cannot be a template
definition'

instead. While 'decltype' solves that problem for expressions of the
type '&T::someVariablename' in template code in VC10, VC9 has the same
problem and there, as I mentioned, there is no solution which I have
been able to discover since 'decltype' does not exist in VC++ prior to
the latest release. So as I mentioned I can use 'decltype' in VC10 for a
solution but I am still without a solution for earlier versions of VC++.
BTW, without the 'decltype' in your example code I do not see why the
code is not valid. Care to explain why VC++ thinks it is necessary ? I
can not imagine not being able to understand '&T::someVariablename' by a
C++ compiler when T is known to be a type.

I will continue to look for a workaround for VC9 and earlier, as I think
my library should be usable by VC9, VC8, and perhaps VC7.1. Thanks for
your neat solution for VC10 !

> template<typename U> static std::false_type helper(...); \
> public: \
> typedef decltype(helper<T>(nullptr)) type; \
> static const bool value = type::value; \
> }; \
> \
> template<typename T, typename X, bool B> \
> struct has_member_ ## NAME ## _of_type_helper \
> : public std::false_type { }; \
> \
> template<typename T, typename X> \
> struct has_member_ ## NAME ## _of_type_helper<T, X, true> \
> : public std::is_same<decltype(&T::NAME), X T::*> { }; \
> \
> template<typename T, typename X> \
> struct has_member_ ## NAME ## _of_type \
> : public has_member_ ## NAME ## _of_type_helper< \
> T, X, has_member_ ## NAME<T>::value> { };
>
> DEFINE_HAS_MEMBER_OF_TYPE(cMem)
>
> struct Gipf { };
>
> struct Dvonn {
> Gipf cMem;
> };
>
> struct Tzaar {
> int cMem;
> };
>
> struct Yinsh {
> int Zertz;
> };
>
> int main() {
> static_assert( has_member_cMem_of_type<Dvonn, Gipf>::value, "one");
> static_assert(!has_member_cMem_of_type<Dvonn, int>::value, "two");
>
> static_assert(!has_member_cMem_of_type<Tzaar, Gipf>::value, "three");
> static_assert( has_member_cMem_of_type<Tzaar, int>::value, "four");
>
> static_assert(!has_member_cMem_of_type<Yinsh, Gipf>::value, "five");
> static_assert(!has_member_cMem_of_type<Yinsh, int>::value, "six");
> }


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