I don't say I write `is_const<MyType>()` instead of
`is_const<MyType>()`. You should probably re-read the text once more,
this time paying attention to the use of parentheses.
I said I don't have a problem with writing `is_const<MyType>()`
("Personally, I'm okay with
`is_const<MyType>()`"). However, `is_const<MyType>()` doesn't work in
all cases (because it relies on a conversion to bool, which doesn't
happen in all contexts). In those rare cases, I don't mind writing
``is_const<MyType>::value` instead ("or `is_const<MyType>::value` in
the exceedingly rare occasions where `is_const<MyType>()` doesn't cut
it."). Those cases are exceedingly rare because I pretty much never
actually want to use `is_const<MyType>()` ("I do a lot of TMP, and
most of the time I just write `is_const<MyType>` anyway). All my
metafunctions that need some bool parameter take a "meta-bool"
parameter instead (what the standard calls a UnaryTypeTrait with a
bool value), so I need neither parentheses nor ::value. It has the
added benefits of resulting in client code with less syntactic noise
(like `EnableIf<is_const<T>>`). It is also usable in templates that
take `template <typename...> class` template arguments, even if those
aren't great and there are better alternatives for higher-order
metafunctions (see Boost.Mpl).
>> type_traits<T>::add_const, where T is a template parameter, is a
>> dependent name. It's **exactly the same** reason add_const<T>::type
>> requires the disambiguator. They both have the form A<T>::C where T is
>> a template parameter and C is a nested type.
>>
>> > In this case you can't
>> > compile your code without the <type_traits> include which shows the
>> > compiler
>> > that add_const::type is indeed a type and not a variable or function.
>>
>> No, the #include does not show anything like that to the compiler.
>> This Stack Overflow answer
>>
>>
http://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords/613132#613132
>> is recommended reading.
>>
> I'm of course fully aware of the basics of disambiguiation and why it is
> needed. The problem is that I find that at least VS2012 requires it even
> when it knows full well that it is a type.
I feel like I am wasting my time on this. To prevent further waste, I
will be totally blunt: no, you are not fully aware of this issue. The
compiler doesn't know full well that it is a type until instantiation,
and MSVC is famous for not requiring typename when it should (because
it doesn't implement two-phase lookup), not the other way around. See
bug report closed as "Deferred":
https://connect.microsoft.com/VisualStudio/feedback/details/742478/support-two-phase-name-lookup.
> You claim that for type_traits<MyType>::add_const a 'typename' would be
> required, in places where it would not for add_const<MyType>::type. This
> makes no sense at all to me. The constructs are totally similar, a typedef
> inside a known class template instantiated for a (potentially) unknown type.
I don't claim any of that, and this slander is the reason I am
bothering to write this reply at all. Right there in a part you quoted
from my reply (so you can't even claim to not have noticed it!) are
phrases like: "It's **exactly the same** reason add_const<T>::type
requires the disambiguator" and "They both have the form [X]". Notice
the use of the word "both" and the use of double asterisks around
"exactly the same" for emphasis. There is also a distinct lack of
words like "but" or "however" in that paragraph. How anyone can draw
the conclusion that I see the two as different? I have no idea, and
that's exactly why I am walking away from this fruitless discussion.
Mit freundlichen Grüßen,
Martinho