Re: [std-proposals] A namespace lookup change to get rid of the _t on the new type_traits.

219 views
Skip to first unread message

Gabriel Dos Reis

unread,
Aug 31, 2013, 3:16:36 PM8/31/13
to std-pr...@isocpp.org
Bengt Gustafsson <bengt.gu...@beamways.com> writes:

[...]

| My suggested solution is:
|
| If two things with the same name are found select the name in the most nested
| namespace if the two conflicting namespaces are nested in each other.

For C++11 and beyond, I would like to see fundamental things such as
name lookup rules enjoy stability. Waking up in the morning and realize
that half of the floor is gone and the living room turned into a
restroom is no fun.

-- Gaby

Bengt Gustafsson

unread,
Sep 1, 2013, 8:33:09 AM9/1/13
to std-pr...@isocpp.org, g...@axiomatics.org
I don't see the problem as the change I suggest only makes currently erroneous code to become legal and well defined. This is nowhere near removing the floor. Of course, if you can show me a case where curreently valid code changes behaviour, that's an entirely different thing.

My motivation was that I don't want to see improved features get worse names than the inferior but older functionality. I would prefer to be able to state that I want to use the new feature instead of the old, using the logical name.

Even if you can show me that the idea of a disambiguation rule such as the one I suggested doesn't work I still think that a mechanism to achieve the end goal would be desirable. At this point I don't really know what would be best. One naive way would be to use a compiler pragma, but compared to a using directive that's very clumsy and error prone.

Martinho Fernandes

unread,
Sep 1, 2013, 9:27:52 AM9/1/13
to std-pr...@isocpp.org
On Sat, Aug 31, 2013 at 8:35 AM, Bengt Gustafsson
<bengt.gu...@beamways.com> wrote:
> As an aside: Could anyone explain to me why type_traits ended up as a
> multitude of single purpose structs in the first place. To me it would have
> been more logical to have one type_traits template like this:
>
>
> template <typename T> struct type_traits {
> typedef const T add_const;
> static const bool is_const = ...;
> };

Why do you find it so? Is something wrong with things that have a
"single purpose"?

> type_traits<MyType>::is_const
>
> vs
>
> is_const<MyType>::type

These two are different things... Personally, I'm okay with
`is_const<MyType>()` or `is_const<MyType>::value` in the exceedingly
rare occasions where `is_const<MyType>()` doesn't cut it. I do a lot
of TMP, and most of the time I just write `is_const<MyType>` anyway,
so I consider this is not-a-problem. Note that *this is still in a
world without the C++14 aliases*.

When it comes to the type transformation traits,
`type_traits<MyType>::add_const` is horrible compared to
`is_const_t<MyType>`. The reason it is horrible is that you have to
write the dreaded typename disambiguator, which IMO makes the code
harder to read because it is essentially noise (humans don't need the
disambiguator because it is obvious from the name that `add_const`
makes a new type). The alias templates don't need the typename
disambiguator, and that's the primary reason for their existence. I
use my own set of type transformation aliases that share their names
with the non-type transformation ones except they are in PascalCase.

> I assume that now with template variables coming up there is a suggestion in
> the wings aimong at removing the ::value of the boolean type traits too. I
> strongly suggest that removing the ::type and the ::value be done in the
> same language version upgrade, and that the same change is done for ALL
> instances of ::type and ::value constructs, regardless of what part of the
> standard library they are used in.

There isn't, and there shouldn't be a suggestion to remove the ::type
or ::value bits **ever**. Those are still useful in a way that the
alias templates cannot be. They allow you to pass around
meta-computations in a lazy manner.

Mit freundlichen Grüßen,

Martinho

Gabriel Dos Reis

unread,
Sep 1, 2013, 9:42:25 AM9/1/13
to std-pr...@isocpp.org
Martinho Fernandes <martinho....@gmail.com> writes:

| There isn't, and there shouldn't be a suggestion to remove the ::type
| or ::value bits **ever**. Those are still useful in a way that the
| alias templates cannot be. They allow you to pass around
| meta-computations in a lazy manner.

This claim has always struck me as odd. You can pass template aliases
as template argument, achieving the same purpose. Resulting in a
cleaner syntax for the majority of uses.

-- Gaby

Gabriel Dos Reis

unread,
Sep 1, 2013, 9:47:17 AM9/1/13
to Bengt Gustafsson, std-pr...@isocpp.org
Bengt Gustafsson <bengt.gu...@beamways.com> writes:

[...]

| Even if you can show me that the idea of a disambiguation rule such as the one
| I suggested doesn't work I still think that a mechanism to achieve the end goal
| would be desirable.

Yes, the two are not necessarily related.

-- Gaby

Martinho Fernandes

unread,
Sep 1, 2013, 9:51:37 AM9/1/13
to std-pr...@isocpp.org
Here's an example. If you write `std::conditional_t<std::is_enum<T>(),
std::underlying_type_t<T>, T>`, that piece of code has undefined
behaviour (or maybe it is ill-formed; I'm not sure which, but both are
bad here), because it always evaluates the type
std::underlying_type<T>::type (underlying_type cannot be used on
non-enums). How would write this using only alias templates?

Mit freundlichen Grüßen,

Martinho

Gabriel Dos Reis

unread,
Sep 1, 2013, 11:20:16 AM9/1/13
to std-pr...@isocpp.org
I am sorry, I do not understand your claim. Are you asking to reproduce
an undefined behavior, or how to reproduce an "ill-formed" program fragment?


-- Gaby

Bengt Gustafsson

unread,
Sep 1, 2013, 6:57:37 PM9/1/13
to std-pr...@isocpp.org


Den söndagen den 1:e september 2013 kl. 15:27:52 UTC+2 skrev R. Martinho Fernandes:
On Sat, Aug 31, 2013 at 8:35 AM, Bengt Gustafsson
<bengt.gu...@beamways.com> wrote:
> As an aside: Could anyone explain to me why type_traits ended up as a
> multitude of single purpose structs in the first place. To me it would have
> been more logical to have one type_traits template like this:
>
>
> template <typename T> struct type_traits {
>     typedef const T add_const;
>     static const bool is_const = ...;
> };

Why do you find it so? Is something wrong with things that have a
"single purpose"?
Namespace pollution. 

> type_traits<MyType>::is_const
>
> vs
>
> is_const<MyType>::type

These two are different things... Personally, I'm okay with
`is_const<MyType>()` or `is_const<MyType>::value` in the exceedingly
rare occasions where `is_const<MyType>()` doesn't cut it. I do a lot
of TMP, and most of the time I just write `is_const<MyType>` anyway,
so I consider this is not-a-problem. Note that *this is still in a
world without the C++14 aliases*.
Are you referring to variable templates here (which would get rid of the trailing() needed for constexpr function implementation?). Either way I don't understand your point, aren't we discussing new C++14 features here? If so they should be able to use other C++14 features.
 

When it comes to the type transformation traits,
`type_traits<MyType>::add_const` is horrible compared to
`is_const_t<MyType>`. The reason it is horrible is that you have to
write the dreaded typename disambiguator, which IMO makes the code
harder to read because it is essentially noise (humans don't need the
disambiguator because it is obvious from the name that `add_const`
makes a new type). The alias templates don't need the typename
disambiguator, and that's the primary reason for their existence. I
use my own set of type transformation aliases that share their names
with the non-type transformation ones except they are in PascalCase.
I think that _t is still better than having the same name in different case versions. Adding PascalCase stuff in namespace std:: would break lots of code for everyone that does a using namespace std and, like you, have done their own things like AddConst.

Also, please enlighten me on why we have to write those tedious typename disambiguators in the cases where the name IS known. 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. Yes, it is concievable that a specialization of add_const for some type would have type being an int, but isn't it enough to check the unspecialized class template and handle the fringe cases when instantiating the template for that T?
 

> I assume that now with template variables coming up there is a suggestion in
> the wings aimong at removing the ::value of the boolean type traits too. I
> strongly suggest that removing the ::type and the ::value be done in the
> same language version upgrade, and that the same change is done for ALL
> instances of ::type and ::value constructs, regardless of what part of the
> standard library they are used in.

There isn't, and there shouldn't be a suggestion to remove the ::type
or ::value bits **ever**. Those are still useful in a way that the
alias templates cannot be. They allow you to pass around
meta-computations in a lazy manner.
I think that the convenience should be optimized for the common cases. Passing things like add_const as a template template parameter would surely be very much more uncommon than other uses. And this is especially true for the predicates which will be much more heavily used with Constraints in the picture.

And I am not saying that these older versions are to go away, I was specifically calling for a mechanism to select which ones to use. Your example shows that my "most nested namespace wins" rule should be augmented with an clause that says that when you explicitly state the name of the outer namespace you really mean it. Like this:

using namespace std;     // This codebase has elected to use std

using namespace std::type_traits_v2;    // This codebase _normally_ uses the new type traits

bool x = is_const<T>;      // Here the new version is selected as there is no explicit qualification

template_meta_program<std::is_const> ...       // Here, as we are sending is_const as a template template parameter we have to use the current version in std, and so we have to qualify despite the using std above.

Note that we are not breaking any code here. If you don't want to use the new type trats you don't have to. Only if you want to use them, but still needs the template template parameter use case do you have to really sift through your code and add std:: where the compiler tells you to.

If you are NOT using std today the line "using namespace std::type_traits_v2;" will select new type_traits, but place them on the global level, which is not what we want (we want them to appear as being in the std namespace). Darned, it doesn't work for this case, does it? A namespace alias like in "namespace std = std::type_traits_v2;" does not work as (at least in VS2012) due to the fact that the lhs name must be unknown in the current scope and std is already the name of another namespace. I think it is arguable that allowing this would be logical as namespaces are open, but it would require yet another language change, albeit also benign as it only makes ill formed programs well defined. And even if this construct could be made to work it would not be very obvious what it does. Being able to sub-use for instance std::rel_ops as if they were in std would however be a somewhat useful feature in general [although the example is really bad, as it contains only operators. But what other namespaces nested in std are there today?].

One idea which would both make the declaration more understandable and the feature less risky would be to explicitly say that things are being added to std:

namespace std += std::type_traits_v2;

Well, not much of an improvement, is it?


Martinho Fernandes

unread,
Sep 2, 2013, 6:07:18 PM9/2/13
to std-pr...@isocpp.org
Oh gosh, so much confusion.

On Mon, Sep 2, 2013 at 12:57 AM, Bengt Gustafsson
<bengt.gu...@beamways.com> wrote:
>> Why do you find it so? Is something wrong with things that have a
>> "single purpose"?
>
> Namespace pollution.

That's something wrong with polluting namespaces, not with things that
have a single purpose. You could simply pack away all the still single
purpose things in a nested namespace, and voilà, no pollution, but
still single purpose structs.

>> These two are different things... Personally, I'm okay with
>> `is_const<MyType>()` or `is_const<MyType>::value` in the exceedingly
>> rare occasions where `is_const<MyType>()` doesn't cut it. I do a lot
>> of TMP, and most of the time I just write `is_const<MyType>` anyway,
>> so I consider this is not-a-problem. Note that *this is still in a
>> world without the C++14 aliases*.
>
> Are you referring to variable templates here (which would get rid of the
> trailing() needed for constexpr function implementation?). Either way I
> don't understand your point, aren't we discussing new C++14 features here?
> If so they should be able to use other C++14 features.

No, I am not referring to variable templates. I am referring to
passing `is_const<MyType>` as a type.

>> When it comes to the type transformation traits,
>> `type_traits<MyType>::add_const` is horrible compared to
>> `is_const_t<MyType>`. The reason it is horrible is that you have to
>> write the dreaded typename disambiguator, which IMO makes the code
>> harder to read because it is essentially noise (humans don't need the
>> disambiguator because it is obvious from the name that `add_const`
>> makes a new type). The alias templates don't need the typename
>> disambiguator, and that's the primary reason for their existence. I
>> use my own set of type transformation aliases that share their names
>> with the non-type transformation ones except they are in PascalCase.
>
> I think that _t is still better than having the same name in different case
> versions. Adding PascalCase stuff in namespace std:: would break lots of
> code for everyone that does a using namespace std and, like you, have done
> their own things like AddConst.

That's kinda sorta irrelevant. People that use `using namespace std`
reap what they sow. Personally it never caused me trouble because I
don't use `using namespace std` and I don't make use of the global
namespace.

> Also, please enlighten me on why we have to write those tedious typename
> disambiguators in the cases where the name IS known.

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.

> Yes,
> it is concievable that a specialization of add_const for some type would
> have type being an int, but isn't it enough to check the unspecialized class
> template and handle the fringe cases when instantiating the template for
> that T?

No, it is not. C++ just doesn't work this way (and it's messy enough as it is)

Bengt Gustafsson

unread,
Sep 3, 2013, 3:39:30 PM9/3/13
to std-pr...@isocpp.org


Den tisdagen den 3:e september 2013 kl. 00:07:18 UTC+2 skrev R. Martinho Fernandes:
Oh gosh, so much confusion.

On Mon, Sep 2, 2013 at 12:57 AM, Bengt Gustafsson
<bengt.gu...@beamways.com> wrote:
>> Why do you find it so? Is something wrong with things that have a
>> "single purpose"?
>
> Namespace pollution.

That's something wrong with polluting namespaces, not with things that
have a single purpose. You could simply pack away all the still single
purpose things in a nested namespace, and voilà, no pollution, but
still single purpose structs.
 
Of course you could tuck them away, but this was no done in the case of type traits, was it?

What I was contemplating was if there was some definite advantage to the design that was selected over the more straightforward imlementation. A guess would be that it was due to the plethora of specializations that would
be needed to fill in the different member types and bools of a type_traits<T> for different types of T, given that you didn't have the different is_const and add_reference etc. already.

If we now view (just as for the _t named usings) the current class templates as a base functionality, this problem with implementing a type_traits template is non-existent. Going in the direction of a type_traits class template would rid us of those _t suffixed that will be really hard to explain in 10 years time. The resulting template could also be the basis for CTTI, which would of course need that the compiler must magically add for instance a special list of members for each specialization of it. This could be done in a later language version.


>> These two are different things... Personally, I'm okay with
>> `is_const<MyType>()` or `is_const<MyType>::value` in the exceedingly
>> rare occasions where `is_const<MyType>()` doesn't cut it. I do a lot
>> of TMP, and most of the time I just write `is_const<MyType>` anyway,
>> so I consider this is not-a-problem. Note that *this is still in a
>> world without the C++14 aliases*.
>
> Are you referring to variable templates here (which would get rid of the
> trailing() needed for constexpr function implementation?). Either way I
> don't understand your point, aren't we discussing new C++14 features here?
> If so they should be able to use other C++14 features.

No, I am not referring to variable templates. I am referring to
passing `is_const<MyType>` as a type.
Ok, let's see, you are passing is_const<MyType> as a type to some template. This template would have to know that the template parameter it gets has only one member and that is ::value. Now there are around 10 dfferent class templates that could be useful for passing like this. Sorry, but I still don't understand your point. I re-read your text above several times but it is too vauge, and also inconsistent in that you say that you write `is_const<MyType>()` instead of `is_const<MyType>()`. Obviously you are doing TMP in very different areas than I have. As is_const<T>::value is static I don't see much of a point in instantiating is_const, and if you do you are stepping out of the TMP realm anyway.

 

>> When it comes to the type transformation traits,
>> `type_traits<MyType>::add_const` is horrible compared to
>> `is_const_t<MyType>`. The reason it is horrible is that you have to
>> write the dreaded typename disambiguator, which IMO makes the code
>> harder to read because it is essentially noise (humans don't need the
>> disambiguator because it is obvious from the name that `add_const`
>> makes a new type). The alias templates don't need the typename
>> disambiguator, and that's the primary reason for their existence. I
>> use my own set of type transformation aliases that share their names
>> with the non-type transformation ones except they are in PascalCase.
>
> I think that _t is still better than having the same name in different case
> versions. Adding PascalCase stuff in namespace std:: would break lots of
> code for everyone that does a using namespace std and, like you, have done
> their own things like AddConst.

That's kinda sorta irrelevant. People that use `using namespace std`
reap what they sow. Personally it never caused me trouble because I
don't use `using namespace std` and I don't make use of the global
namespace.
I hope that this type of arrogance is not too widespread in the C++ standards committee. I'm sure that there are lots of major code bases out there which do using namespace std. I would say that as long as you stick to
lower case names it is not so much of a problem but with the new names for constraints, for instance std::Object such code bases will be very badly hurt. It is not going to help C++ reputation if such severe breaking changes are introduced, even if the users have transgressed a programming rule. The problem is that the short term advantage of not having to write std:: on all library names. 

Also: I have been working over 10 years with a code base we started with in 1994. For several years the compilers we used didn't even have namespaces. We had a third party STL which had a #define to disable namespaces where the compilers didn't have them. When we got a compiler with namespaces we already had over 500 000 lines worth of code using STL containers, algorithms etc. The only practical solution to migrate to the new compiler with namespaces and an STL in std was of course to add a "using namespace std" in a header everyone includes. I'm sure that there are lots of code bases like this out there.


> Also, please enlighten me on why we have to write those tedious typename
> disambiguators in the cases where the name IS known.

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.

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.

And yes, at least in VS2012 you need the 'typename' for both cases if MyType is a template parameter but not if it is a concrete type.

In this case, except for odd cases where a specialization replaces a type in the base implementation with a value in the specialization the compiler would have no problem deducing that type in add_const<MyType>::type
is a type. That's written in the add_const class head. You don't have to see the MyType class head to know this, and of course you won't as when parsing it is just a T.

Thus my original question was perfectly valid.

I did a very un-scientific scan for typename disambiguation cases in a small code base I have. It contained around 60 places where I had had to write 'typename' to disambiguate. Interestingly ALL of them were of the form: known_template<template-parameter>::type, about half of them enable_if and half the different remove_const, decay etc.
 
> Yes,
> it is concievable that a specialization of add_const for some type would
> have type being an int, but isn't it enough to check the unspecialized class
> template and handle the fringe cases when instantiating the template for
> that T?

No, it is not. C++ just doesn't work this way (and it's messy enough as it is)
 
"C++ just doesn't work that way" is a really bad answer in a group with the purpose of discussing changes and improvements to the language.

DeadMG

unread,
Sep 3, 2013, 5:59:35 PM9/3/13
to std-pr...@isocpp.org
I hope that this type of arrogance is not too widespread in the C++ standards committee.
 
It absolutely is. This is exactly what you get when you using namespace std; you get name clashes with all future names added to std. If you don't like it, don't use namespace std. In fact, I can tell you that I attended Bristol and was in a LEWG meeting where this issue was raised, and my memory of that event is that we decided to not care whatsoever.

"C++ just doesn't work that way" is a really bad answer in a group with the purpose of discussing changes and improvements to the language.

You're not talking about some detail or obscure corner. Changing this fact would require re-engineering a LOT of the language. That's way more than can be achieved today. 

Nevin Liber

unread,
Sep 3, 2013, 6:25:13 PM9/3/13
to std-pr...@isocpp.org
On 3 September 2013 14:39, Bengt Gustafsson <bengt.gu...@beamways.com> wrote:
Also: I have been working over 10 years with a code base we started with in 1994. For several years the compilers we used didn't even have namespaces. We had a third party STL which had a #define to disable namespaces where the compilers didn't have them. When we got a compiler with namespaces we already had over 500 000 lines worth of code using STL containers, algorithms etc. The only practical solution to migrate to the new compiler with namespaces and an STL in std was of course to add a "using namespace std" in a header everyone includes.

You are saying that the only practical solution was to adopt what was, even in 2004, widely known to be an extremely poor practice <http://www.drdobbs.com/using-me/184401782>?

You had another choice, but you chose to do an expedient hack.  IMO, while the committee isn't going to deliberately break your code base, the committee isn't going to spend any effort protecting your code base in this instance, either.  If it were my responsibility, I'd bite the bullet and fix it right, sooner rather than later (and in previous jobs it has been and I did).
--
 Nevin ":-)" Liber  <mailto:ne...@eviloverlord.com(847) 691-1404

Richard Smith

unread,
Sep 3, 2013, 6:43:28 PM9/3/13
to std-pr...@isocpp.org
These days, this is not even a particularly big bullet to bite.

The Clang project would certainly accept a tool to replace a using-directive with explicit qualification or per-source-file using-declarations (maybe as part of the C++11 migrator, soon to be renamed clang-modernize). Such a tool should be pretty simple to write, and much easier than manually fixing a 0.5 MLoC codebase. Some documentation here:

http://clang.llvm.org/docs/LibTooling.html

Bengt Gustafsson

unread,
Sep 3, 2013, 8:00:51 PM9/3/13
to std-pr...@isocpp.org
Well, finally something useful. If a tool like that migrator (which I haven't checked out yet) had been available around 2000 when we got the namespace-aware compiler (certainly way before 2004 anyway), we would surely have used it. But biting such bullets was certainly not an option, I am 100% sure that the reply from management would have been "stick with the old compiler then" if I had suggested such an effort to be able to upgrade the compiler.

Martinho Fernandes

unread,
Sep 3, 2013, 8:53:50 PM9/3/13
to std-pr...@isocpp.org
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

Bengt Gustafsson

unread,
Sep 4, 2013, 4:06:20 AM9/4/13
to std-pr...@isocpp.org
Ok, not to waste too much of youtr time, you were right, after about four more re-reads I could decipher your text about the trailing () into something logical. It was the or not being ment as being alternatives between the two adjoining quoted examples but in a longer part of the sentence that fooled me. Clearly I should expect a programming language expert like you to be able to write prose exactly right, although I still think the wording was a bit contrived.

And I made a fool of myself again on the second issue regarding the typename. I was assuming that you were claiming this as a drawback for the type_traits<T> solution as the argument "these two solutions have the same disadvantage and therefore solution A is better" didn't seem to be a rational argument. As far as I remember I wasn't claiming any reduction in the use of 'typename' for my solution.

Of course, with the current language specification the Microsoft compiler is too lenient on typename, and in contrast with its other shortcomings in this area it does not show up as an error message at the time of actual instantiation as by that time all the details of the referred template including specializations are known. This will create porting problems when programmers forget typename. This issue is however only vaguely connected to my question. I can't imagine that the compiler, after having parsed the <type_traits> header would have no information that there is a typedef called type in the add_const class template. Maybe the Microsoft compiler hasn't but that has already been defined as a shortcoming. I don't see the point in the standard continuing to prevent compilers from using this information to help programmers. I have now written this up as a separate subject, so there is no point in discussing it further here.
Reply all
Reply to author
Forward
0 new messages