Boost logo

Boost :

From: Andrei Alexandrescu (andrei_at_[hidden])
Date: 2008-04-09 13:11:14


Howard Hinnant wrote:
> On Apr 8, 2008, at 9:40 PM, Steven Watanabe wrote:
>> AMDG
>>
>> Howard Hinnant wrote:
>>>> template <class T, class U>
>>>> decltype(true ? T() : U()) Min(T&& a, U&& b) {
>>>> return b < a ? b : a;
>>>> }
>>>>
>> Should this really work if T of U is a reference type and thus cannot
>> be default constructed?
>
> You're right. Not by current language rules. The reported error
> message could have been better.

I knew this is going to come. That's why I'd tried this with conceptg++:

typedef const int& cintr;
typedef int& cint;

int main()
{
     int a;
     int x = cintr();
     int y = cint();
}

Turns out this program compiles fine. I assumed the compiler was right,
and I was also self-pressured to make Min's definition self-contained,
so I just went with that trick.

> By coincidence I'm dealing with a similar problem here: http://home.twcny.rr.com/hinnant/cpp_extensions/time2_demo.html
> , and dealing with it via a promote trait, quite similar to what
> I've seen in boost. I.e. the Min signature might look like:
>
> template <class T, class U> typename promote<T, U>::type Min(T&&
> a, U&& b);
>
> With the *default* (and preferably standardized) promote trait looking
> like:
>
> template <class T, class U>
> struct promote
> {
> private:
> static T t;
> static U u;
> public:
> typedef decltype(true ? static_cast<T&&>(t) :
> static_cast<U&&>(u)) type;
> };
>
> // promote is specializable for client-defined types

So it does look like there is a simple solution to min and max! Any
interest in submitting a revised 2199?

Oh, and in order to save space and default-constructor-related
aggravation, you may want to use static functions in lieu of static
variables. In the process, I also changed name to what I think is a
better one:

template <class T, class U>
struct common_type
{
private:
      static T t();
      static U u();
public:
      typedef decltype(true ? static_cast<T&&>(t()) :
static_cast<U&&>(u())) type;
};

Actually, heck, just have the functions return the rvalue ref directly:

template <class T, class U>
struct common_type
{
private:
      static T&& t();
      static U&& u();
public:
      typedef decltype(true ? t() : u()) type;
};

Then you define Min like this:

template <class T, class U>
typename common_type<T, U>::type
Min(T&& a, U&& b) {
     return b < a ? b : a;
}

and you're home free. At least my few tests pass fine.

I think you're dead on that common_type/promote belongs to the standard.
I'd defined a template called CommonType in the D standard library:

http://www.digitalmars.com/d/2.0/phobos/std_traits.html#CommonType

and it turned out to be mightily useful. (Notice that it takes a
variable number of types.)

Andrei


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