52

Why does C++ have public members that anyone can call and friend declarations that expose all private members to given foreign classes or methods but offer no syntax to expose particular members to given callers?

I want to express interfaces with some routines to be invoked only by known callers without having to give those callers complete access to all privates, which feels like a reasonable thing to want. The best I could come up with myself (below) and suggestions by others so far revolve around idioms/pattern of varying indirectness, where I really just want a way to have single, simple class definitions that explicitly indicate what callers (more granularly than me, my children, or absolutely anybody) can access which members. What is the best way to express the concept below?

// Can I grant Y::usesX(...) selective X::restricted(...) access more cleanly?
void Y::usesX(int n, X *x, int m) {
  X::AttorneyY::restricted(*x, n);
}

struct X {
  class AttorneyY;          // Proxies restricted state to part or all of Y.
private:
  void restricted(int);     // Something preferably selectively available.
  friend class AttorneyY;   // Give trusted member class private access.
  int personal_;            // Truly private state ...
};

// Single abstract permission.  Can add more friends or forwards.
class X::AttorneyY {
  friend void Y::usesX(int, X *, int);
  inline static void restricted(X &x, int n) { x.restricted(n); }
};

I'm nowhere near being a software organization guru, but it feels like interface simplicity and the principle of least privilege are directly at odds in this aspect of the language. A clearer example for my desire might be a Person class with declared methods like takePill(Medicine *) tellTheTruth() and forfeitDollars(unsigned int) that only Physician, Judge, or TaxMan instances/member methods, respectively, should even consider invoking. Needing one-time proxy or interface classes for each major interface aspect sits ill with me, but please speak up if you know I'm missing something.

Answer accepted from Drew Hall: Dr Dobbs - Friendship and the Attorney-Client Idiom

The code above originally called the wrapper class 'Proxy' instead of 'Attorney' and used pointers instead of references but was otherwise equivalent to what Drew found, which I then deemed the best generally known solution. (Not to pat myself on the back too hard...) I also changed the signature of 'restricted' to demonstrate parameter forwarding. The overall cost of this idiom is one class and one friend declaration per permission set, one friend declaration per set approved caller, and one forwarding wrapper per exposed method per permission set. Most of the better discussion below revolves around the forwarding call boilerplate that a very similar 'Key' idiom avoids at the expense of less direct protection.

idmean
  • 13,418
  • 7
  • 47
  • 78
Jeff
  • 3,347
  • 2
  • 22
  • 33
  • I think this is an interesting language design question - how would your ideal language handle this? But this seems just far too over-engineered for the small amount of times that friends are required. For more granular access control than public/protected/private, usually a comment or function name prefix suffices. I prefer the python approach - which is "users should do the right thing" instead of the futile attempt at enforcing it. – Stephen Jul 10 '10 at 17:00
  • @Stephen: The usual C++ approach is to catch as many possible errors at compile-time as possible. I think Matthieus approach is close to what i'd want from language support: Allow access per class or function based on groups. – Georg Fritzsche Jul 10 '10 at 17:18
  • @Georg : I think the C++ approach is to allow access insofar as the language allows. That level of access control would be nice, but I don't think creating dummy key objects is something I would design into a language :) Sure, it mostly achieves the goal (ignoring the fact that keys can be passed around), but - in my opinion - is more work than should be devoted to the topic :) I'm ok agreeing to disagree on this with you all, and maybe I'd change my mind if I worked in your codebase. – Stephen Jul 10 '10 at 17:55
  • 1
    @Stephen: If language integration was possible i was more thinking along the lines of `AccessGroup foo { class A; void f(); };` and `void g() restrictedTo(foo);`. Oh well, one can dream... :) – Georg Fritzsche Jul 10 '10 at 18:01
  • @Georg : Nice idea, I was thinking some kind of decorator approach, similar to python or java decorators (like @Access(Foo) ). Maybe this is addressed in c++2x :) – Stephen Jul 10 '10 at 18:09
  • 1
    @Stephen: I agree more with Georg about code encouragement of proper module use. If trust is the real safeguard, private access needn't even exist, and I prefer to have the code itself enforce policy. Plenty of zealots believe that all comments are evil, being at best merely _accurate_ and even then only when perfect. I do like the integration syntax you put forward, but I would also like even terser options like `void g() restrictedTo;`. I've not really considered the grammar, but full entities might not always be necessary. – Jeff Jul 10 '10 at 18:58
  • @Georg: In my fantasy land, I'd like something along these lines sometime, but I can't ever grasp where the standards committee's priorities lie. I love `constexpr` and `static_assert` in C++0x (_1x_ yet?) and was greatly saddened by the removal of `concept`; the emphasis on compile-time safety seems inconsistent to me. – Jeff Jul 10 '10 at 19:06
  • Your terser version should actually basically be possible as an extension using [attributes](http://www2.research.att.com/~bs/C++0xFAQ.html#attributes). Maybe someone has too much time and pushs it into Clang? ;) Note that concepts are only post-poned they would have delayed the new standard even more, see [here](http://cpp-next.com/archive/2009/08/what-happened-in-frankfurt/). – Georg Fritzsche Jul 10 '10 at 19:29
  • @Georg: Yeah, I've read about all the drama, but it really boils down to them not being even available as unsupported TR components for a few years and not likely in the proper language for maybe a decade plus. Treating templates more as compile-time entities than tweaky link-time disasters-in-waiting would really have been nice. _sigh_... – Jeff Jul 10 '10 at 20:34

6 Answers6

70

There is a very simple pattern, which has retro-actively been dubbed PassKey, and which is very easy in C++11:

template <typename T>
class Key { friend T; Key() {} Key(Key const&) {} };

And with that:

class Foo;

class Bar { public: void special(int a, Key<Foo>); };

And the call site, in any Foo method, looks like:

Bar().special(1, {});

Note: if you are stuck in C++03, skip to the end of the post.

The code is deceptively simple, it embeds a few key points that are worth elaborating.

The crux of the pattern is that:

  • calling Bar::special requires copying a Key<Foo> in the context of the caller
  • only Foo can construct or copy a Key<Foo>

It is notable that:

  • classes derived from Foo cannot construct or copy Key<Foo> because friendship is not transitive
  • Foo itself cannot hand down a Key<Foo> for anyone to call Bar::special because calling it requires not just holding on to an instance, but making a copy

Because C++ is C++, there are a few gotchas to avoid:

  • the copy constructor has to be user-defined, otherwise it is public by default
  • the default constructor has to be user-defined, otherwise it is public by default
  • the default constructor has to be manually defined, because = default would allow aggregate initialization to bypass the manual user-defined default constructor (and thus allow any type to get an instance)

This is subtle enough that, for once, I advise you to copy/paste the above definition of Key verbatim rather than attempting to reproduce it from memory.


A variation allowing delegation:

class Bar { public: void special(int a, Key<Foo> const&); };

In this variant, anyone having an instance of Key<Foo> can call Bar::special, so even though only Foo can create a Key<Foo>, it can then disseminate the credentials to trusted lieutenants.

In this variant, to avoid a rogue lieutenant leaking the key, it is possible to delete the copy constructor entirely, which allows tying the key lifetime to a particular lexical scope.


And in C++03?

Well, the idea is similar, except that friend T; is not a thing, so one has to create a new key type for each holder:

class KeyFoo { friend class Foo; KeyFoo () {} KeyFoo (KeyFoo const&) {} };

class Bar { public: void special(int a, KeyFoo); };

The pattern is repetitive enough that it might be worth a macro to avoid typos.

Aggregate initialization is not an issue, but then again the = default syntax is not available either.


Special thanks to people who helped improving this answer over the years:

  • Luc Touraille, for pointing to me in the comments that class KeyFoo: boost::noncopyable { friend class Foo; KeyFoo() {} }; completely disables the copy constructor and thus only works in the delegation variant (preventing storing instance).
  • K-ballo, for pointing out how C++11 improved the situation with friend T;
Community
  • 1
  • 1
Matthieu M.
  • 251,718
  • 39
  • 369
  • 642
  • I have to wonder why you're passing the FooKey by reference. ;) Seems an odd thing to do with an empty, unused object. Other than that, I like the idea, and I've done the same before on an ad-hoc basis, but this is the first time I really consider it as a general pattern. +1 – jalf Jul 10 '10 at 12:08
  • I'm trying to make Foo's interface itself show and enforce self-restricting behavior, but it seems as though this technique just hopes that a 'FooKey &' won't get passed to some calling method not trusted to be competent, non-malicious, and sufficiently justified in making restricted calls. Is there some advantage in this style over the Attourney-Client idiom linked to above? – Jeff Jul 10 '10 at 15:52
  • @Jeff: Note that `FooKey` can only be constructed (and thus passed to the method) by its friends due to its constructor being private. Compared to the Attorney idiom / proxying its *much* more concise. – Georg Fritzsche Jul 10 '10 at 16:32
  • 1
    I opened [a question](http://stackoverflow.com/questions/3220009/is-this-key-oriented-access-protection-pattern-a-known-idiom) regarding the naming of this pattern. – Georg Fritzsche Jul 10 '10 at 16:44
  • @Georg: It's definitely more concise, but that seems mitigated somewhat by needing to add extra parameters to restricted methods and quite possibly to explicitly prohibit FooKey copying, etc.. Passing nominally empty classes or references to them also seems to require some trivial amount of overhead, while the static attorney approach seems that it could be fully streamlined out at compilation. – Jeff Jul 10 '10 at 18:25
  • @Matthieu: I think that the attorney approach is what I really want, but this is definitely a very good solution as well. Thanks for the input, +1 vote. – Jeff Jul 10 '10 at 18:25
  • 1
    @Jeff: I'd say every decent compiler should optimize empty classes away for pass-by-value where you don't start to take its address or similar. But i agree that i downplayed the intrusiveness somewhat. – Georg Fritzsche Jul 10 '10 at 18:32
  • Matthieu, we got two new questions if you're interested: [naming](http://stackoverflow.com/questions/3324248/how-to-name-this-key-oriented-access-protection-pattern) and [improving re-usability](http://stackoverflow.com/questions/3324898/can-we-increase-the-re-usability-of-this-key-oriented-access-protection-pattern). – Georg Fritzsche Jul 25 '10 at 09:12
  • 1
    Are you sure your solution using `boost::noncopyable` works correctly? To pass the key by value, `Foo` needs to have access to the copy constructor of `FooKey`, which cannot be compiled since it needs access to the one of `boost::noncopyable`. In think that to make this work, you need to drop `noncopyable` and simply make the copy constructor private (after all, the class is not really noncopyable, copying it is just restricted to friends). – Luc Touraille Jun 07 '12 at 16:02
  • @LucTouraille: I would say "works on my machine", but we all know how much this is worth... – Matthieu M. Jun 07 '12 at 16:19
  • Hum, this is weird, AFAIK there is no way for `FooKey` to be copied: it cannot access `noncopyable` constructor since it is private, and the friend declaration does not give any additional access to `Foo` (it only gives access to the names accessible in `FooKey`). Does [this code](http://ideone.com/AYQZm) compiles without errors on your machine? – Luc Touraille Jun 07 '12 at 16:51
  • @LucTouraille: The edit is dated from 2 years ago. I hoped it did compile back then, but I won't bet anything on it, and I do not have the compiler I used then (sorry). If it may reassure you, I do find it fishy too. I suppose redeclaring the copy constructor as private would do the trick better ? (it does seem to: http://ideone.com/GOb1w) – Matthieu M. Jun 07 '12 at 18:50
  • Yes, I think the private constructor is more correct. I'm sorry that I bumped this old answer of yours, but if you wanted it to stay buried, you should not have linked it in your profile :)! – Luc Touraille Jun 07 '12 at 21:22
  • @LucTouraille: No problem, I am just surprised the issue went unnoticed for 2 years! – Matthieu M. Jun 08 '12 at 06:14
  • I would call this the Attorney-Client-Key Idiom as it is only a syntactic variation -- you trade inlined function calls for zero-length method parameters. GCC -O3 compiled an example with two inlined functions vs. the keys to the same size (did not disassemble and compare) as you would expect. The difference was that I used the key-version twice in the code to fix a bug I didn't want to take the time to fix in the full Attorney-Client Idiom. – Jonathan Seng Apr 17 '13 at 17:33
  • 1
    And don't forget the awesome invocation syntax: `Bar b; b.special( 3, {} );` We could also do `static struct unlock_request_t {} use_key; template class only_allow { friend class T; only_allow(unlock) {}; only_allow(only_allow const&)=delete; }`, which changes the access pattern to `Bar b; b.special( 3, use_key );` ;) – Yakk - Adam Nevraumont Sep 11 '14 at 20:27
18

The Attorney-Client idiom may be what you're looking for. The mechanics are not too different from your member proxy class solution, but this way is more idiomatic.

Drew Hall
  • 26,700
  • 10
  • 58
  • 79
  • I know of this by name only, and what I've glanced at so far looks very promising. This may be what I'm looking for. Thanks! – Jeff Jul 10 '10 at 01:45
  • OK everybody, this is almost verbatim what I reinvented, and I think that the link deserves a read. The difference is that in the published form, the helper class is called XAttourney as opposed to X::Proxy2, and the wrapped calls use references instead of pointers. I'm going to split the difference, making members called X::YAttourney that use static calls on references. Since this is about as well researched and canonical an answer as I'm going to get for 'how', I'm accepting this and will split 'why is friend itself all or nothing' into a new question later. – Jeff Jul 10 '10 at 15:20
3

You can use a pattern described in Jeff Aldger's book 'C++ for real programmers'. It has no special name but there it is referred as 'gemstones and facets'. The basic idea is as following: among your main class that contains all the logic, you define several interfaces (not real interfaces, just like them) that implements sub-parts of that logic. Each of those interface (facet in terms of book) provides access to some of logic of main class (gemstone). Also, each facet holds the pointer to gemstone instance.

What does this mean for you?

  1. You can use any facet everywhere instead of gemstone.
  2. Users of facets doesn't have to know about gemstone structure, as in could be forward-declared and used through PIMPL-pattern.
  3. Other classes can refer to facet rather to gemstone - this is the answer to your question about how to expose limited nubmer of methods to specified class.

Hope this helps. If you want, I could post code samples here to illustrate this pattern more clearly.

EDIT: Here's the code:

class Foo1; // This is all the client knows about Foo1
class PFoo1 { 
private: 
 Foo1* foo; 
public: 
 PFoo1(); 
 PFoo1(const PFoo1& pf); 
 ~PFoo(); 
 PFoo1& operator=(const PFoo1& pf); 

 void DoSomething(); 
 void DoSomethingElse(); 
}; 
class Foo1 { 
friend class PFoo1; 
protected: 
 Foo1(); 
public: 
 void DoSomething(); 
 void DoSomethingElse(); 
}; 

PFoo1::PFoo1() : foo(new Foo1) 
{} 

PFoo1::PFoo(const PFoo1& pf) : foo(new Foo1(*(pf
{} 

PFoo1::~PFoo() 
{ 
 delete foo; 
} 

PFoo1& PFoo1::operator=(const PFoo1& pf) 
{ 
 if (this != &pf) { 
  delete foo; 
  foo = new Foo1(*(pf.foo)); 
 } 
 return *this; 
} 

void PFoo1::DoSomething() 
{ 
 foo->DoSomething(); 
} 

void PFoo1::DoSomethingElse() 
{ 
 foo->DoSomethingElse(); 
} 

Foo1::Foo1() 
{ 
} 

void Foo1::DoSomething() 
{ 
 cout << “Foo::DoSomething()” << endl; 
} 

void Foo1::DoSomethingElse() 
{ 
 cout << “Foo::DoSomethingElse()” << endl; 
} 

EDIT2: Your class Foo1 could be more complex, for example, it contains two another methods:

void Foo1::DoAnotherThing() 
{ 
 cout << “Foo::DoAnotherThing()” << endl; 
} 

void Foo1::AndYetAnother() 
{ 
 cout << “Foo::AndYetAnother()” << endl; 
} 

And they're accessible via class PFoo2

class PFoo2 { 
    private: 
     Foo1* foo; 
    public: 
     PFoo2(); 
     PFoo2(const PFoo1& pf); 
     ~PFoo(); 
     PFoo2& operator=(const PFoo2& pf); 

     void DoAnotherThing(); 
     void AndYetAnother(); 
    };
void PFoo1::DoAnotherThing() 
    { 
     foo->DoAnotherThing(); 
    } 

    void PFoo1::AndYetAnother() 
    { 
     foo->AndYetAnother(); 
    } 

Those methods are not in PFoo1 class, so you cannot access them through it. In this way you can split the behavior of Foo1 to two (or more) facets PFoo1 and PFoo2. Those facets classes could be used in different places, and their caller shoudn't be aware of Foo1 implementation. Maybe it's not what you really want, but what you want is impossible for C++, and this is a work-aroud, but maybe too verbose...

Haspemulator
  • 10,462
  • 9
  • 46
  • 70
  • Thanks for the post, but I'm not sure I'm clear on this pattern's purpose. It seems like vanilla pImpl-style implementation hiding, where I just want a flat but selective interface description. Could you expound a bit on its nuances? – Jeff Jul 10 '10 at 01:43
2

I know this is an old question, but the problem is still relevant. While I like the idea of the Attorney-Client idiom, I wanted a transparent interface for client classes that had been granted private (or protected) access.

I imagine something similar to this has been done already, but a cursory look around didn't turn up anything. The following method (C++11 up) works on a per class (not per object) basis and uses a CRTP base class that is used by the 'private class' to expose a public functor. Only those classes that have specifically been given access can call the functor's operator(), which then directly invokes the associated private method via a stored reference.

There is no function call overhead and the only memory overhead is one reference per private method that requires exposure. The system is very versatile; any function signature and return type is permitted as is calling virtual functions in the private class.

For me, the main benefit is one of syntax. While an admittedly rather ugly declaration of the functor objects is required in the private class, this is completely transparent to the client classes. Here is an example taken from the original question:

struct Doctor; struct Judge; struct TaxMan; struct TheState;
struct Medicine {} meds;

class Person : private GranularPrivacy<Person>
{
private:
    int32_t money_;
    void _takePill (Medicine *meds) {std::cout << "yum..."<<std::endl;}
    std::string _tellTruth () {return "will do";}
    int32_t _payDollars (uint32_t amount) {money_ -= amount; return money_;}

public:
    Person () : takePill (*this), tellTruth (*this), payDollars(*this) {}

    Signature <void, Medicine *>
        ::Function <&Person::_takePill>
            ::Allow <Doctor, TheState> takePill;

    Signature <std::string>
        ::Function <&Person::_tellTruth>
            ::Allow <Judge, TheState> tellTruth;

    Signature <int32_t, uint32_t>
        ::Function <&Person::_payDollars>
            ::Allow <TaxMan, TheState> payDollars;

};


struct Doctor
{
    Doctor (Person &patient)
    {
        patient.takePill(&meds);
//        std::cout << patient.tellTruth();     //Not allowed
    }
};

struct Judge
{
    Judge (Person &defendant)
    {
//        defendant.payDollars (20);            //Not allowed
        std::cout << defendant.tellTruth() <<std::endl;
    }
};

struct TheState
{
    TheState (Person &citizen)                  //Can access everything!
    {
        citizen.takePill(&meds);
        std::cout << citizen.tellTruth()<<std::endl;
        citizen.payDollars(50000);
    };
};

The GranularPrivacy base class works by defining 3 nested template classes. The first of these, 'Signature', takes the function return type and function signature as template parameters, and forwards these to both the functor's operator() method and the the second nest template class, 'Function'. This is parametrized by a pointer to a private member function of the Host class, which must have the signature provided by the Signature class. In practice, two separate 'Function' classes are used; the one given here, and another for const functions, omitted for brevity.

Finally the Allow class recursively inherits from a explicitly instantiated base class using the variadic template mechanism, depending on the number of classes specified in it's template argument list. Each inheritance level of Allow has one friend from the template list, and the using statements bring the base class constructor and operator () up the inheritance hierarchy into the most derived scope.

template <class Host> class GranularPrivacy        
{
    friend Host;
    template <typename ReturnType, typename ...Args> class Signature
    {
        friend Host;
        typedef ReturnType (Host::*FunctionPtr) (Args... args);
        template <FunctionPtr function> class Function
        {
            friend Host;
            template <class ...Friends> class Allow
            {
                Host &host_;
            protected:
                Allow (Host &host) : host_ (host) {}
                ReturnType operator () (Args... args) {return (host_.*function)(args...);}
            };
            template <class Friend, class ...Friends>
            class Allow <Friend, Friends...> : public Allow <Friends...>
            {
                friend Friend;
                friend Host;
            protected:
                using Allow <Friends...>::Allow;
                using Allow <Friends...>::operator ();
            };
        };
    };
};

I hope somebody finds this useful, any comments or suggestions would be most welcome. This is definitely still work in progress - I would particularly like to merge the Signature and Function classes into just one template class, but have been struggling to find a way to do this. More complete, runnable examples can be found at cpp.sh/6ev45 and cpp.sh/2rtrj.

Heathen
  • 21
  • 4
  • I like this approach as it preserves the function call, unlike keypass or attorney-client. Additionally, I imagine it's possible to give this some sane compile errors with `static_assert` and the like. However, for the life of me I can't get this to compile on my environment, VS2017 C++17. The latter link (cpp.sh/2rtrj) spits out a bunch of compile errors. After a couple of minor changes (see cpp.sh/9d55s) I get something legible: – t.y Jul 02 '18 at 04:32
  • `'GranularPrivacy::Signature::Function::Allow::operator ()': cannot access protected member declared in class 'GranularPrivacy::Signature::Function::Allow'`. Actually, all the `TheState` calls fail for me, with VS telling me that `function GranularPrivacy:: ... ::Allow::operator() [with Host=Person, ...., Friends=<>]" is inaccesible`. Do you have any insight into these errors? – t.y Jul 02 '18 at 04:37
  • Sad, we don't have variadic friend. – Jarod42 Nov 04 '20 at 17:47
0

Something akin to the code below will allow you fine-grained control over which parts of your private state you make public through the friend keyword.

class X {
  class SomewhatPrivate {
    friend class YProxy1;

    void restricted();
  };

public:
  ...

  SomewhatPrivate &get_somewhat_private_parts() {
    return priv_;
  }

private:
  int n_;
  SomewhatPrivate priv_;
};

BUT:

  1. I don't think it's worth the effort.
  2. The need to use the friend keyword might suggest your design is flawed, perhaps there's a way you can do what you need without it. I try to avoid it but if it makes the code more readable, maintainable or reduces the need for boilerplate code I use it.

EDIT: To me the code above is (usually) an abomination that should (usually) not be used.

Staffan
  • 1,731
  • 13
  • 14
  • The use of friendship does not imply that a design is flawed. An inappropriate use of friendship does, but from the context of this question we cannot infer that. People fear friendship because, as they claim, it violates encapsulation. Instead, when used properly, it actually benefits encapsulation. [Ref Stroustrup] – Shirik Jul 10 '10 at 01:21
  • Shirik: Hence "might suggest" – Staffan Jul 10 '10 at 01:22
  • The statement "might suggest" is entirely based on the predicate "the use of friendship exists". This correlation should not exist. – Shirik Jul 10 '10 at 01:23
  • What I'm after is not really about data hiding but about granting high-level routine access to trusted interfaces. There is absolutely no _need_ to use friend here, but I would strongly prefer to be able to control in as flat a manner as possible what can be externally accessed. – Jeff Jul 10 '10 at 01:35
0

I have written a minor improvement to the solution given by Matthieu M. The limitation of his solution is that you can only grant access to a single class. What if I want to let any one of three classes have access?

#include <type_traits>
#include <utility>

struct force_non_aggregate {};

template<typename... Ts>
struct restrict_access_to : private force_non_aggregate {
    template<typename T, typename = typename std::enable_if<(... or std::is_same<std::decay_t<T>, std::decay_t<Ts>>{})>::type>
    constexpr restrict_access_to(restrict_access_to<T>) noexcept {}
    restrict_access_to() = delete;
    restrict_access_to(restrict_access_to const &) = delete;
    restrict_access_to(restrict_access_to &&) = delete;
};

template<typename T>
struct access_requester;

template<typename T>
struct restrict_access_to<T> : private force_non_aggregate {
private:
    friend T;
    friend access_requester<T>;

    restrict_access_to() = default;
    restrict_access_to(restrict_access_to const &) = default;
    restrict_access_to(restrict_access_to &&) = default;
};

// This intermediate class gives us nice names for both sides of the access
template<typename T>
struct access_requester {
    static constexpr auto request_access_as = restrict_access_to<T>{};
};


template<typename T>
constexpr auto const & request_access_as = access_requester<T>::request_access_as;

struct S;
struct T;

auto f(restrict_access_to<S, T>) {}
auto g(restrict_access_to<S> x) {
    static_cast<void>(x);
    // f(x); // Does not compile
}

struct S {
    S() {
        g(request_access_as<S>);
        g({});
        f(request_access_as<S>);
        // f(request_access_as<T>); // Does not compile
        // f({request_access_as<T>});   // Does not compile
    }
};

struct T {
    T() {
        f({request_access_as<T>});
        // g({request_access_as<T>}); // Does not compile
        // g({}); // Does not compile
    }
};

This uses a slightly different approach to making the object not an aggregate. Rather than having a user-provided constructor, we have an empty private base class. In practice, it probably does not matter, but it means that this implementation is a POD class because it remains trivial. The effect should remain the same, however, because no one is going to be storing these objects anyway.

David Stone
  • 22,053
  • 14
  • 61
  • 77
  • Does this solution may work for this question : https://stackoverflow.com/questions/53172759/templated-attorney-client-idiom-for-more-many-classes – Blood-HaZaRd Nov 06 '18 at 15:34