
On Apr 9, 2008, at 1:11 PM, Andrei Alexandrescu wrote:
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.
Interesting, thanks.
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.)
That's a nice improvement, thanks. -Howard