Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

What I'm doing wrong here?

33 views
Skip to first unread message

Heinz Müller

unread,
Apr 22, 2019, 11:09:37 AM4/22/19
to
#include <type_traits>

using namespace std;

template<typename T>
void f123( typename enable_if<is_unsigned<T>::value, T>::type t )
{
}

int main()
{
unsigned u;
int i;

f123( u );
f123( i ); // shoudn't work
}

Why dows the compiler not find at least the "valid" unsigned f123?

Kenny McCormack

unread,
Apr 22, 2019, 11:14:01 AM4/22/19
to
In article <q9klf7$gah$1...@news.albasani.net>,
Your program has undefined behavior, so anything is possible.

And, anything is right.

And, so on...

--
Religion is what keeps the poor from murdering the rich.

- Napoleon Bonaparte -

Manfred

unread,
Apr 22, 2019, 12:34:30 PM4/22/19
to
I'm not sure why, but typically enable_if is used either on template
arguments or on return value types.
It works if rewritten as follows:


#include <type_traits>
#include <iostream>

using namespace std;

template<typename T, typename =
typename enable_if<is_unsigned<T>::value, T>::type>
void f123( T t )
{
cout << "f123(" << t << ")" << endl;
}

int main()
{
unsigned u = 1;
int i = 2;

f123( u );
f123( i ); // shoudn't work
}

(I added the required initializers to get rid of UB)

Manfred

unread,
Apr 22, 2019, 12:40:42 PM4/22/19
to
As said, also with return types:

#include <type_traits>
#include <iostream>

using namespace std;

template<typename T>
typename enable_if<is_unsigned<T>::value, void>::type f123( T t )

Heinz Müller

unread,
Apr 22, 2019, 1:12:15 PM4/22/19
to

>> template<typename T, typename =
>>    typename enable_if<is_unsigned<T>::value, T>::type>
>> void f123( T t )
>> {
>>    cout << "f123(" << t << ")" << endl;
>> }
>>

> As said, also with return types:
> ...
> template<typename T>
> typename enable_if<is_unsigned<T>::value, void>::type f123( T t )
> {
>   cout << "f123(" << t << ")" << endl;
> }

That seems more intuitive.
But what does the ", typename = ..." above mean?
----------

Manfred

unread,
Apr 22, 2019, 4:40:55 PM4/22/19
to
That is an unnamed template argument, with a default that is the result
of enable_if.
In the template it is a placeholder for a type argument that is not used
- in fact it is used only to trigger the evaluation of its default type,
which is the result of the enable_if expression.

Alf P. Steinbach

unread,
Apr 22, 2019, 5:25:47 PM4/22/19
to
Template argument deduction doesn't work on *dependent* types, like the
...::type for your formal argument.

From the compiler's point of view there could be any number of
specializations of `enable_if`, with `::type`s that didn't at all
resemble the `T` type. And these specialization could be defined in
indirect ways that involved much compile time activity to straighten
out. It would be unreasonable to require it to do that /in general/.

Template argument deduction is instead a more or less direct matching,
not considering any type indirection.

So, to do what you're trying to do, do

template<
class T,
class = enable_if_t< is_unsigned_v< T > >
>
void f123( const T value ) ...

Due to historical reasons, that template aliases were not available at
the time the `enable_if` appeared, the notation is full of annoying
ticks and warts like `_t` and `_v`.

I tend to reduce them via ¹simple aliases, e.g., off the cuff

template< bool condition > using Enable_if_ =
std::enable_if_t<condition>;

In some cases, such as `is_const_` and `is_base_and_derived_`, the
wrapper or alias also adds much needed generality or clarity.


Cheers!

- Alf

References:
¹ E.g. see <url:
https://github.com/alf-p-steinbach/cppx-core/blob/master/source/cppx-core/language/tmp/basic-type-traits.hpp>

Heinz Müller

unread,
Apr 23, 2019, 12:53:55 AM4/23/19
to
> That is an unnamed template argument, ...

Are there other purposes of this kind of template-argument?

Manfred

unread,
Apr 23, 2019, 8:50:39 AM4/23/19
to
On 4/23/2019 6:53 AM, Heinz Müller wrote:
>> That is an unnamed template argument, ...
>
> Are there other purposes of this kind of template-argument?
>
This is similar to unnamed function arguments:
"Typically, unnamed arguments arise from the simplification of code or
from planning ahead for extensions. In both cases, leaving the argument
in place, although unused, ensures that callers are not affected by the
change."

This is in Bjarne's book (TC++PL) about function arguments, but the
explanation can be transposed to template arguments too.
0 new messages