Topic: auto leaks private types


Author: Marius Stoica <letto2@gmail.com>
Date: Sun, 20 Jun 2010 14:49:39 CST
Raw View
Hi,
I've come across an undesired behaviour of auto
This happens with GCC 4.4

class Size {
enum class ESize {
   small, large
};
   ESize value;
public :
static const ESize
   small = ESize::small,
   large = ESize::large;
Size(ESize a):value{a}{}
};

//..

Size a = Size::small; // ok
// Error: Size::ESize  x = Size::small;
auto b = Size::small;// ??? i'd like this to be a Size;
typedef decltype(b) ESize; // ??

comments?

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Mon, 21 Jun 2010 00:23:39 CST
Raw View
On 20 Jun., 22:49, Marius Stoica <let...@gmail.com> wrote:
> I've come across an undesired behaviour of auto
> This happens with GCC 4.4
>
> class Size {
> enum class ESize {
>    small, large};
>
>    ESize value;
> public :
> static const ESize
>    small = ESize::small,
>    large = ESize::large;
> Size(ESize a):value{a}{}
> };
>
> //..
>
> Size a = Size::small; // ok
> // Error: Size::ESize  x = Size::small;
> auto b = Size::small;// ??? i'd like this to be a Size;

You are misunderstanding auto here. Your comment
implies that you also expect that within

template<class T> void foo(T t) {
 static_assert(std::is_same<Size, T>::value, "Ouch");
}

int main() {
 foo(Size::small);
}

the assertion would hold, alas, it does not. In fact, auto
behaves very similar to the effect of function templates
that deduce their argument types.

> typedef decltype(b) ESize; // ??
>
> comments?

Another comment in regard to leaking: No, I don't agree
that auto is "leaking" here. Access control in C++ is
*not* access control of types and other entities, but
it is only access control of *names*, see class 11,
[class.access]/1:

"1 A member of a class can be
    private; that is, its **name** can be used only by members
and friends of the class in which it is declared. [..]"

(Emphasis mine). This simply means that a function template
can deduce the type of Size::small, even though it could *name*
this type as Size::ESize. The same rules apply to auto and
similarly to decltype. E.g.

typedef decltype(Size::small) TS;

immediately deduces TS as having the same type as
const Size::ESize (again, without being able to name
it as such).

In summary: You are mis-using auto, if you want to
initialize a type T with a source value of type U.
Obviously you need to name the destination type
explicitly, because auto would just allow for the
*same* type as the source value.

HTH & Greetings from Bremen,

Daniel Kr   gler



--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Alf P. Steinbach /Usenet" <alf.p.steinbach+usenet@gmail.com>
Date: Mon, 21 Jun 2010 00:22:37 CST
Raw View
* Marius Stoica, on 20.06.2010 22:49:
>
> Hi,
> I've come across an undesired behaviour of auto
> This happens with GCC 4.4
>
> class Size {
> enum class ESize {
>    small, large
> };
>    ESize value;
> public :
> static const ESize
>    small = ESize::small,
>    large = ESize::large;
> Size(ESize a):value{a}{}
> };
>
> //..
>
> Size a = Size::small; // ok
> // Error: Size::ESize  x = Size::small;
> auto b = Size::small;// ??? i'd like this to be a Size;
> typedef decltype(b) ESize; // ??
>
> comments?

Well, it has been discussed before. Summing up, with 'auto' it's far
*easier* to *inadvertently* leak private types than it was in C++98.

In C++98 it could happen, like


<code>
   class Size
   {
   private:
       struct E
       {
           enum Size { small, large };
       };

       E::Size value_;

   public :
       static const E::Size    small = E::small;
       static const E::Size    large = E::large;

       Size( E::Size a ): value_( a ) {}
   };

   template< class T >
   void foo( T ) {}

   int main()
   {
       foo( Size::small );     // Private type leaked (or loken?).
   }
</code>


But I think it's far too easy with 'auto'.


Cheers,

- Alf

--
blog at <url: http://alfps.wordpress.com>

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: =3D?ISO-8859-1?Q?Daniel_Kr=3DFCgler?=3D <daniel.kruegler@googlemail.c=.om>
Date: Mon, 21 Jun 2010 12:01:52 CST
Raw View
On Jun 21, 8:23 am, Daniel Kr=FCgler <daniel.krueg...@googlemail.com>
wrote:
[..]
> This simply means that a function template can deduce the type
> of Size::small, even though it could *name* this type as
                                                     ^
Somehow an internet demon must have removed the word "not" at
the position marked above ;-)

> Size::ESize. The same rules apply to auto and similarly to
> decltype. E.g.

- Daniel


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use
mailto:std-c++@netlab.cs.rpi.edu<std-c%2B%2B@netlab.cs.rpi.edu>
]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]