restrict constructor access in variadic template class

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP


restrict constructor access in variadic template class



I want to create a statically checked builder. Something along these lines:


class HasDough;
class HasCheese;

template <typename ... CurrentTypes>
class Pizza {
public:
friend Pizza<> startPizzaMaking();

Pizza<HasDough, CurrentTypes ...> addDough(){
return Pizza<HasDough, CurrentTypes ...>();
}

Pizza<HasCheese, CurrentTypes ...> addCheese(){
return Pizza<HasCheese, CurrentTypes ...>();
}

public: // I want to change to private
Pizza() = default;
};


Pizza<> startPizzaMaking() {
return Pizza<>();
}



use it like this:


int main(){
auto pizza = startPizzaMaking()
.addDough()
.addCheese();

return 0;
}



Now I can go along and check the current types with a disjunction. That way I can make sure everything is added.



My Problem is:
Each step along the way I create a new builder instance and want to pass my current state. For that the constructor should be private and I would use the friend function to obtain a new builder.



How can I restrict access to the constructor to force others to use the factory but internally I can still use it?



[update]



simply making the constructor private doesn't work. The code will expand to something like this:


Pizza<HasDough>::addCheese() {
return Pizza<HasCheese, HasDough>(); // fine with public constructor, not so with private
}





First, what's wrong with Pizza<>().addDough().addCheese()? Second, if you are so inclined, make the constructor private and the factory a friend of Pizza.
– n.m.
20 mins ago


Pizza<>().addDough().addCheese()


Pizza





... and also make the template a friend of itself, this way: template <typename ...> friend class Pizza;
– n.m.
11 mins ago


template <typename ...> friend class Pizza;




1 Answer
1



Different class template specialisations are completely separate classes and have no access to internals of each other. Fortunately there are always friends to save your day.


template <typename ... CurrentTypes>
class Pizza {
public:
friend Pizza<> startPizzaMaking();

Pizza<HasDough, CurrentTypes ...> addDough(){
return Pizza<HasDough, CurrentTypes ...>();
}

Pizza<HasCheese, CurrentTypes ...> addCheese(){
return Pizza<HasCheese, CurrentTypes ...>();
}

private: // OK
Pizza() = default;

friend Pizza<> startPizzaMaking();
// make every specialisation a friend of every other <=== this here trick
template <typename ...> friend class Pizza;
};

Pizza<> startPizzaMaking() {
return Pizza<>();
}





Thanks, will try once I get to a PC. I already had the friend for the factory though ;)
– rad i
1 min ago








By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Arduino Mega cannot recieve any sketches, stk500_recv() programmer is not responding

Visual Studio Code: How to configure includePath for better IntelliSense results

C++ virtual function: Base class function is called instead of derived