C++ Logo

std-proposals

Advanced search

Re: Make class template parameters available externally

From: Andrey Semashev <andrey.semashev_at_[hidden]>
Date: Thu, 31 Oct 2019 20:54:12 +0300
On 2019-10-31 15:15, Dmitry wrote:
>
> Decomposing the type to know the template parameters is not the same as
> making these parameters part of the class' public interface.
>
>
> Right, not exactly the same.
>
> There are
> cases when template parameters are used for auxiliary purposes, e.g.
> for
> SFINAE or tagging and specialization. These parameters should not be
> exposed.
>
> It looks like this statement is the most important thing. And I am
> struggling to understand why it is so. Can you please elaborate on this
> more? Why do you think it is a bad idea? (I hope you read my proposal
> and know that if there is already a user-defined type with the same
> name, they won't be declared).

I did not read the paper, but name clashes is not my main point above.
Currently, template parameter names are not part of the class interface.
Even some trailing template parameters themselves may not be intended
for public use, although careful programmers would hide those with
template aliases or inheritance.

   template< typename T, bool F = is_empty_v<T> && !is_final_v<T> >
   struct is_ebo_viable_impl : false_type {};

   template< typename T >
   struct is_ebo_viable_impl< T, true > : true_type {};

   template< typename T >
   using is_ebo_viable = is_ebo_viable_impl< T >;

In this example, neither T nor F names are the public interface of
is_ebo_viable or is_ebo_viable_impl. The F parameter itself is not even
intended to be used by users, it is an implementation detail. If those
names became visible to users, that would mean they are now part of the
class interface, which is not the intention. Worse, there would be no
way to hide F, which is_ebo_viable attempts to achieve.

Adding unintended members to types can have practical consequences. For
example, various type inspection techniques can be broken.

   template< typename type >
   struct foo {};

   template< typename T >
   struct has_type
   {
     static constexpr value = ...; // true if T::type is a type
   };

has_type<foo>::value is false now, but with the implicit template
parameter names propagation it would become true.


Speaking of name clashes, I think it should be a hard error if a
template parameter name clashes a member name, when parameter name
propagation is requested.

   template< public typename T >
   struct foo
   {
     typedef int T; // error: member type T already defined
                    // by the template parameter
   };

This will avoid the ambiguity as to what T actually is for the less
experienced developers.

Received on 2019-10-31 12:56:34