Boost logo

Boost :

Subject: Re: [boost] [type trait extension] I hate volatile...
From: Frédéric Bron (frederic.bron_at_[hidden])
Date: 2011-07-22 04:44:01


> What does your code look like that detects void types?  I use the following
> EXPR_IS_VOID macro myself (which is not originally mine, but I think I have
> modified it from the original after some testing); feel free to pilfer.  The
> double comma operator thingy is intended to work even if the type of ( Expr
> ) has an overloaded comma operator, but I've found that GCC has issues with
> this construct, hence the two versions.

Thank you for help. I have tested your code for void detection which
GNUC version gives identical results to the one I use (on msvc, g++
and intel):

namespace detail {\
        struct returns_void_t {};
        static ::boost::type_traits::yes_type returns_void(returns_void_t);\
        static ::boost::type_traits::no_type returns_void(int);\
}
template <typename T> int operator,(const T&, ::detail::returns_void_t);
template <typename T> int operator,(const volatile T&,
::detail::returns_void_t);

#define RETURNS_VOID_IMPL(Expr)\
                sizeof(::boost::type_traits::yes_type)\
                ==\
                sizeof(::detail::returns_void(((Expr), ::detail::returns_void_t())))

Here are the results (best viewed in fixed size font) of void detection with
functions returning various types (int of class X) with various cv qualifiers
and by-value or reference:

                     | g++ | g++ |icpc |msvc |
return type |4.3.2|4.5.2|10.0 | 10 |
                     |4.3.4|4.5.3|11.1 | |
                     |4.4.4|4.6.0|12.0 | |
void | 1 | 1 | 1 | 1 |
int | 0 | 0 | 0 | 0 |
int const | 0 | 0 | 0 | 0 |
int volatile | 1 | 0 | 0 | 0 |
int const volatile | 1 | 0 | 0 | 0 |
int & | 0 | 0 | 0 | 0 |
int const & | 0 | 0 | 0 | 0 |
int volatile & | 0 | 0 | 0 | 0 |
int const volatile & | 0 | 0 | 0 | 0 |
X | 0 | 0 | 0 | 0 |
X const | 0 | 0 | 0 | 0 |
X volatile | 1 | 1 |fail | 0 |
X const volatile | 1 | 1 |fail | 0 |
X & | 0 | 0 | 0 | 0 |
X const & | 0 | 0 | 0 | 0 |
X volatile & | 0 | 0 | 0 | 0 |
X const volatile & | 0 | 0 | 0 | 0 |

So only msvc gives the right answer, i.e. detects void returning only when void
returning. g++ from version 4.5 says that any cv qualifiers for by-value int is
ignored which improves the answer for those return types but returning a class
by value with volatile qualifiers fails to complile with intel compiler and
gives the wrong answer with g++. I wonder why the code gives the right answer
withmsvc.

I found another issue with g++ (all versions up to 4.6.0) (works fine
with msvc 10
and intel 12): although g++ behaves well with fundamental types
returned by value,
the result of postfix operator++ applied to an int volatile is detected as void!
The standard states in 13.6/3 (Built-in operators):
"For every pair (T, VQ), where T is an arithmetic type, and VQ is
either volatile
or empty, there exist candidate operator functions of the form
VQ T& operator++(VQ T&);
T operator++(VQ T&, int);"

That means that for an "int volatile" variable the corresponding built-in
operator should be:
int operator++(int volatile &, int);
and according to the table above this should be correctly detected as returning
non-void. Note that prefix operator++ works fine.
This is the program that fails (writes true) with g++ (4.5.2 and 4.6.0):

#include <iostream>
#include <iomanip>
#include <boost/type_traits/detail/yes_no_type.hpp>

namespace detail {\
   struct returns_void_t {};
   static ::boost::type_traits::yes_type returns_void(returns_void_t);\
   static ::boost::type_traits::no_type returns_void(int);\
}
template <typename T> int operator,(const T&, ::detail::returns_void_t);
template <typename T> int operator,(const volatile T&,
::detail::returns_void_t);

#define RETURNS_VOID(Expr)\
   sizeof(::boost::type_traits::yes_type)\
   ==\
   sizeof(::detail::returns_void(((Expr), ::detail::returns_void_t())))

int main() {
   int volatile one_int_volatile;
   std::cout<<std::boolalpha<<"RETURNS_VOID:
"<<(RETURNS_VOID((one_int_volatile++)))<<'\n';
   return 0;
}

Frédéric


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