C++ Logo

std-proposals

Advanced search

Re: Make class template parameters available externally

From: Dmitry <dimanne_at_[hidden]>
Date: Sat, 2 Nov 2019 08:07:02 +0000
>
> it wouldn't try to add new member entities to the template; instead, it
> would just make the names of the existing entities visible. That is, we'd
> have something like
>

> struct Widget { bool operator==(const Widget&) const = default; };
> template<public Widget W> struct Gadget {
> static_assert(std::is_same_v<decltype(W), Widget>); // C++2a:
> decltype(W) is not a reference type
> const Widget *myw() { return &W; }
> };
> int main() {
> Gadget<Widget{}> g;
> Gadget<Widget{}> h;
> static_assert(std::is_same_v<decltype(g), decltype(h)>); // C++2a
> assert(g.myw() == h.myw()); // C++2a
> const Widget *p = &decltype(g)::W; // new proposed feature
> const Widget *q = &g.W; // new proposed feature
> assert(p == g.myw()); // Presumably g.W denotes the same entity
> outside the class as inside it
> assert(q == g.myw()); // Ditto
>
> using WTYPE = decltype(g.W); // new proposed feature
> static_assert(std::is_same_v<WTYPE, Widget>); // Presumably
> decltype(g.W) is not a reference type
> }
>
> Offhand, I would not expect `Gadget` to have a "member" `W` in any sense;
> for example, I would not expect `W` to be visible to a program that used
> the Reflection TS to get a list of Gadget's static data members.
>

If we chose this approach, would not it mean that various type-inspection
techniques said that there is no W in Gadget, and yet it were possible to
write decltype(g)::W? If I understood your correctly, this behaviour will
be surprising...


> I’m also still questioning whether this proposal is necessary as an
> opt-in feature, as we can
> > effectively do this already, with a combination of using declarations,
> and constexpr field declarations.
>

I would hazard a guess, that (nearly) everything that we have in C++ now
was possible in C++98 or even C: indeed, methods are just functions that
implicitly take "special pointer this" (possible in plain C), overloaded
functions and namespaces - are just a matter of mangling (possible in C),
variadic templates were emulated (to some degree) via a bunch of overloaded
functions, lambdas - are completely useless, they did not introduce
anything conceptually new, constexpr if() - was possible since C++98 and so
on and so on...
Of course we can do it by manually typing using declarations. But I still
cannot understand why it means that this proposal is useless.



> Absolutely. This proposal has no reason to exist. It does not save any
> library implementor any work at all.
>
Ok, are you using "*at all*" literally here (or you just exaggerating)? If
literally, than this table shows exactly how it saves work:

Before

After

template <class _A,

          int _B,

          template<class> class _C

>

struct X {

public:

   using A = _A;

protected:

   static constexpr int B = _B;

private:

   template<class T>

   using C = _C<T>;

};

template<public typename A,

         protected int B,

         private template<class> class C

>

struct X {

};


It produces more questions than it answers. At best, it provides an
> error-prone alternative way to accomplish *something that you can already
> accomplish cleanly within the existing language* (ever since C++98).
>
Again, this proposal is not about achieving something that was previously
completely impossible to achieve in C++. As with 99% of all C++ features -
it is syntax sugar and/or more clear way of expressing a developer's intent.

I advise the proposer to (A) drop it, but at least (B) study the history of
> proposals for "keyword arguments." P0671
> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0671r2.html> is
> a great place to start. I suggest this because the proposal is no more or
> less than "keyword arguments for template arguments instead of function
> arguments," and it has all the same philosophical problems. Ville gave a
> bunch of them.
>
Yep, I will have a look.

(For example, what happens if two declarations are in scope, and they use
> two different names for the same argument? The current proposal doesn't
> address this, except to say that definitions take priority over
> non-definition declarations. It doesn't say how to tiebreak between two
> non-definition declarations.)
>
If I understood you correctly, you are asking about this case:
template <public class X>
class Foo;
template <public class Y>
class Foo;

Foo::{X or Y}?

If yes, then according to the initial desire to reason about the feature as
implicitly generated *in the definition of a class* typedefs, it should
issue an error (since there is no definition). But you probably asked the
question under a slightly different assumption of what you described above
("*it wouldn't try to add new member entities to the template; instead, it
would just make the names of the existing entities visible*").

-- 
Dmitry
*Sent from gmail*

Received on 2019-11-02 03:09:47