Inheriting private CRTP constructor using friend declaration












0














I have problems understanding the correct behavior of inheriting constructors from a base class.
In my particular case, I have a crtp-base class with private constructors in order to prevent an instantiation of the base class (as abstract class).
Now, the crtp-base befriends the derived class and the derived class inherits the base class constructors with a using statement. This works well for the default, copy and move constructor but fails for custom constructors. Is there a way to achieve this without reimplenting all constructors in the derived class?



#include <iostream>

template <typename d_t>
class base
{
friend d_t;

base()
{
std::cout << "base: ctor()n";
}
base(base const & other) = default;
base(base && other) = default;

base(int)
{
std::cout << "base: ctor()n";
}
};

class derived: public base<derived>
{
public:

using base<derived>::base;
};

int main()
{
derived d{};
derived d1{d};
derived d2{std::move(d1)};
// derived d3{1}; //does not compile!
}


EDIT



AFAIK cppreference says that accessibility of constructors is not changed by the access specifier of the using declaration in the derived class, which is different to other member functions. But I have seen this kind of code compiling and running and I am not sure if I understood the using-declaration correctly.
Of course I'll investigate the other code further to see what is going on but I wanted to know if there is something hidden that I might miss.










share|improve this question
























  • friend d_t; that looks wrong?
    – Yakk - Adam Nevraumont
    Nov 23 at 0:39










  • @Yakk-AdamNevraumont Why?
    – songyuanyao
    Nov 23 at 0:50










  • _t is reserved in POSIX?
    – user4581301
    Nov 23 at 1:07






  • 1




    Making the derived class a friend does not make much sense as you would get almost the same effect by make everything protected instead of private. The main difference would be if you derive other classes from your derived classes but given that you are using the CRTP pattern, it is probably not the case. Thus in the end, I think you are using the wrong tool for the job.
    – Phil1970
    Nov 23 at 1:12










  • @Phil1970 true. I coluld make it protected. And if I understand en.cppreference.com/w/cpp/language/using_declaration correct then it should not even work. It is just that I've seen this kind of code compiling and I am completely out of explanation why? So I was wondering if there is a bit that I am not aware of which makes this work.
    – guest3450132
    Nov 23 at 9:03


















0














I have problems understanding the correct behavior of inheriting constructors from a base class.
In my particular case, I have a crtp-base class with private constructors in order to prevent an instantiation of the base class (as abstract class).
Now, the crtp-base befriends the derived class and the derived class inherits the base class constructors with a using statement. This works well for the default, copy and move constructor but fails for custom constructors. Is there a way to achieve this without reimplenting all constructors in the derived class?



#include <iostream>

template <typename d_t>
class base
{
friend d_t;

base()
{
std::cout << "base: ctor()n";
}
base(base const & other) = default;
base(base && other) = default;

base(int)
{
std::cout << "base: ctor()n";
}
};

class derived: public base<derived>
{
public:

using base<derived>::base;
};

int main()
{
derived d{};
derived d1{d};
derived d2{std::move(d1)};
// derived d3{1}; //does not compile!
}


EDIT



AFAIK cppreference says that accessibility of constructors is not changed by the access specifier of the using declaration in the derived class, which is different to other member functions. But I have seen this kind of code compiling and running and I am not sure if I understood the using-declaration correctly.
Of course I'll investigate the other code further to see what is going on but I wanted to know if there is something hidden that I might miss.










share|improve this question
























  • friend d_t; that looks wrong?
    – Yakk - Adam Nevraumont
    Nov 23 at 0:39










  • @Yakk-AdamNevraumont Why?
    – songyuanyao
    Nov 23 at 0:50










  • _t is reserved in POSIX?
    – user4581301
    Nov 23 at 1:07






  • 1




    Making the derived class a friend does not make much sense as you would get almost the same effect by make everything protected instead of private. The main difference would be if you derive other classes from your derived classes but given that you are using the CRTP pattern, it is probably not the case. Thus in the end, I think you are using the wrong tool for the job.
    – Phil1970
    Nov 23 at 1:12










  • @Phil1970 true. I coluld make it protected. And if I understand en.cppreference.com/w/cpp/language/using_declaration correct then it should not even work. It is just that I've seen this kind of code compiling and I am completely out of explanation why? So I was wondering if there is a bit that I am not aware of which makes this work.
    – guest3450132
    Nov 23 at 9:03
















0












0








0







I have problems understanding the correct behavior of inheriting constructors from a base class.
In my particular case, I have a crtp-base class with private constructors in order to prevent an instantiation of the base class (as abstract class).
Now, the crtp-base befriends the derived class and the derived class inherits the base class constructors with a using statement. This works well for the default, copy and move constructor but fails for custom constructors. Is there a way to achieve this without reimplenting all constructors in the derived class?



#include <iostream>

template <typename d_t>
class base
{
friend d_t;

base()
{
std::cout << "base: ctor()n";
}
base(base const & other) = default;
base(base && other) = default;

base(int)
{
std::cout << "base: ctor()n";
}
};

class derived: public base<derived>
{
public:

using base<derived>::base;
};

int main()
{
derived d{};
derived d1{d};
derived d2{std::move(d1)};
// derived d3{1}; //does not compile!
}


EDIT



AFAIK cppreference says that accessibility of constructors is not changed by the access specifier of the using declaration in the derived class, which is different to other member functions. But I have seen this kind of code compiling and running and I am not sure if I understood the using-declaration correctly.
Of course I'll investigate the other code further to see what is going on but I wanted to know if there is something hidden that I might miss.










share|improve this question















I have problems understanding the correct behavior of inheriting constructors from a base class.
In my particular case, I have a crtp-base class with private constructors in order to prevent an instantiation of the base class (as abstract class).
Now, the crtp-base befriends the derived class and the derived class inherits the base class constructors with a using statement. This works well for the default, copy and move constructor but fails for custom constructors. Is there a way to achieve this without reimplenting all constructors in the derived class?



#include <iostream>

template <typename d_t>
class base
{
friend d_t;

base()
{
std::cout << "base: ctor()n";
}
base(base const & other) = default;
base(base && other) = default;

base(int)
{
std::cout << "base: ctor()n";
}
};

class derived: public base<derived>
{
public:

using base<derived>::base;
};

int main()
{
derived d{};
derived d1{d};
derived d2{std::move(d1)};
// derived d3{1}; //does not compile!
}


EDIT



AFAIK cppreference says that accessibility of constructors is not changed by the access specifier of the using declaration in the derived class, which is different to other member functions. But I have seen this kind of code compiling and running and I am not sure if I understood the using-declaration correctly.
Of course I'll investigate the other code further to see what is going on but I wanted to know if there is something hidden that I might miss.







c++ using friend crtp






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 23 at 9:16

























asked Nov 23 at 0:27









guest3450132

11




11












  • friend d_t; that looks wrong?
    – Yakk - Adam Nevraumont
    Nov 23 at 0:39










  • @Yakk-AdamNevraumont Why?
    – songyuanyao
    Nov 23 at 0:50










  • _t is reserved in POSIX?
    – user4581301
    Nov 23 at 1:07






  • 1




    Making the derived class a friend does not make much sense as you would get almost the same effect by make everything protected instead of private. The main difference would be if you derive other classes from your derived classes but given that you are using the CRTP pattern, it is probably not the case. Thus in the end, I think you are using the wrong tool for the job.
    – Phil1970
    Nov 23 at 1:12










  • @Phil1970 true. I coluld make it protected. And if I understand en.cppreference.com/w/cpp/language/using_declaration correct then it should not even work. It is just that I've seen this kind of code compiling and I am completely out of explanation why? So I was wondering if there is a bit that I am not aware of which makes this work.
    – guest3450132
    Nov 23 at 9:03




















  • friend d_t; that looks wrong?
    – Yakk - Adam Nevraumont
    Nov 23 at 0:39










  • @Yakk-AdamNevraumont Why?
    – songyuanyao
    Nov 23 at 0:50










  • _t is reserved in POSIX?
    – user4581301
    Nov 23 at 1:07






  • 1




    Making the derived class a friend does not make much sense as you would get almost the same effect by make everything protected instead of private. The main difference would be if you derive other classes from your derived classes but given that you are using the CRTP pattern, it is probably not the case. Thus in the end, I think you are using the wrong tool for the job.
    – Phil1970
    Nov 23 at 1:12










  • @Phil1970 true. I coluld make it protected. And if I understand en.cppreference.com/w/cpp/language/using_declaration correct then it should not even work. It is just that I've seen this kind of code compiling and I am completely out of explanation why? So I was wondering if there is a bit that I am not aware of which makes this work.
    – guest3450132
    Nov 23 at 9:03


















friend d_t; that looks wrong?
– Yakk - Adam Nevraumont
Nov 23 at 0:39




friend d_t; that looks wrong?
– Yakk - Adam Nevraumont
Nov 23 at 0:39












@Yakk-AdamNevraumont Why?
– songyuanyao
Nov 23 at 0:50




@Yakk-AdamNevraumont Why?
– songyuanyao
Nov 23 at 0:50












_t is reserved in POSIX?
– user4581301
Nov 23 at 1:07




_t is reserved in POSIX?
– user4581301
Nov 23 at 1:07




1




1




Making the derived class a friend does not make much sense as you would get almost the same effect by make everything protected instead of private. The main difference would be if you derive other classes from your derived classes but given that you are using the CRTP pattern, it is probably not the case. Thus in the end, I think you are using the wrong tool for the job.
– Phil1970
Nov 23 at 1:12




Making the derived class a friend does not make much sense as you would get almost the same effect by make everything protected instead of private. The main difference would be if you derive other classes from your derived classes but given that you are using the CRTP pattern, it is probably not the case. Thus in the end, I think you are using the wrong tool for the job.
– Phil1970
Nov 23 at 1:12












@Phil1970 true. I coluld make it protected. And if I understand en.cppreference.com/w/cpp/language/using_declaration correct then it should not even work. It is just that I've seen this kind of code compiling and I am completely out of explanation why? So I was wondering if there is a bit that I am not aware of which makes this work.
– guest3450132
Nov 23 at 9:03






@Phil1970 true. I coluld make it protected. And if I understand en.cppreference.com/w/cpp/language/using_declaration correct then it should not even work. It is just that I've seen this kind of code compiling and I am completely out of explanation why? So I was wondering if there is a bit that I am not aware of which makes this work.
– guest3450132
Nov 23 at 9:03














1 Answer
1






active

oldest

votes


















0














The short answer is yes, just make them public in the base class. Inherited constructors have the same accessibility in the derived class as they do in the base. There's no way to make a private base class constructor public in the derived class.



But abstract base classes can't be instantiated on their own anyway. There's no need to make their constructors private.



CRTP has no bearing on any of the above. If you only needed it for the friend declaration, then you can do without the pattern.



class base
{
public:
base()
{
}

base(int)
{
std::cout << "base: ctor()n";
}

virtual void foo() = 0;
};

class derived: public base
{
public:
using base::base;

void foo() override
{
// details...
}
};

int main()
{
derived d{};
derived d1{d};
derived d2{std::move(d1)};
derived d3{1}; //Works!!
}


Further reading on cppreference: Using-declaration






share|improve this answer





















  • Thanks for the reply. I know that this solves the problem, but going to virtual polymorphism is not an option. The code is completely based on static polymorphism.
    – guest3450132
    Nov 23 at 9:09












  • What did you mean by "as abstract class" in the original question?
    – Peter Ruderman
    Nov 23 at 12:36












  • Abstract means, that in order to avoid misuse of the CRTP base class, it should not be instantiable without a dreived class. To prevent a wrong inheritance (a derived class that gives a wrong derived type to the CRTP) you need to make the constructors private and befriend the derived class. This way only the derived class can call the base class constructors and thus can be instantiated.
    – guest3450132
    Nov 30 at 9:21











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53439372%2finheriting-private-crtp-constructor-using-friend-declaration%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














The short answer is yes, just make them public in the base class. Inherited constructors have the same accessibility in the derived class as they do in the base. There's no way to make a private base class constructor public in the derived class.



But abstract base classes can't be instantiated on their own anyway. There's no need to make their constructors private.



CRTP has no bearing on any of the above. If you only needed it for the friend declaration, then you can do without the pattern.



class base
{
public:
base()
{
}

base(int)
{
std::cout << "base: ctor()n";
}

virtual void foo() = 0;
};

class derived: public base
{
public:
using base::base;

void foo() override
{
// details...
}
};

int main()
{
derived d{};
derived d1{d};
derived d2{std::move(d1)};
derived d3{1}; //Works!!
}


Further reading on cppreference: Using-declaration






share|improve this answer





















  • Thanks for the reply. I know that this solves the problem, but going to virtual polymorphism is not an option. The code is completely based on static polymorphism.
    – guest3450132
    Nov 23 at 9:09












  • What did you mean by "as abstract class" in the original question?
    – Peter Ruderman
    Nov 23 at 12:36












  • Abstract means, that in order to avoid misuse of the CRTP base class, it should not be instantiable without a dreived class. To prevent a wrong inheritance (a derived class that gives a wrong derived type to the CRTP) you need to make the constructors private and befriend the derived class. This way only the derived class can call the base class constructors and thus can be instantiated.
    – guest3450132
    Nov 30 at 9:21
















0














The short answer is yes, just make them public in the base class. Inherited constructors have the same accessibility in the derived class as they do in the base. There's no way to make a private base class constructor public in the derived class.



But abstract base classes can't be instantiated on their own anyway. There's no need to make their constructors private.



CRTP has no bearing on any of the above. If you only needed it for the friend declaration, then you can do without the pattern.



class base
{
public:
base()
{
}

base(int)
{
std::cout << "base: ctor()n";
}

virtual void foo() = 0;
};

class derived: public base
{
public:
using base::base;

void foo() override
{
// details...
}
};

int main()
{
derived d{};
derived d1{d};
derived d2{std::move(d1)};
derived d3{1}; //Works!!
}


Further reading on cppreference: Using-declaration






share|improve this answer





















  • Thanks for the reply. I know that this solves the problem, but going to virtual polymorphism is not an option. The code is completely based on static polymorphism.
    – guest3450132
    Nov 23 at 9:09












  • What did you mean by "as abstract class" in the original question?
    – Peter Ruderman
    Nov 23 at 12:36












  • Abstract means, that in order to avoid misuse of the CRTP base class, it should not be instantiable without a dreived class. To prevent a wrong inheritance (a derived class that gives a wrong derived type to the CRTP) you need to make the constructors private and befriend the derived class. This way only the derived class can call the base class constructors and thus can be instantiated.
    – guest3450132
    Nov 30 at 9:21














0












0








0






The short answer is yes, just make them public in the base class. Inherited constructors have the same accessibility in the derived class as they do in the base. There's no way to make a private base class constructor public in the derived class.



But abstract base classes can't be instantiated on their own anyway. There's no need to make their constructors private.



CRTP has no bearing on any of the above. If you only needed it for the friend declaration, then you can do without the pattern.



class base
{
public:
base()
{
}

base(int)
{
std::cout << "base: ctor()n";
}

virtual void foo() = 0;
};

class derived: public base
{
public:
using base::base;

void foo() override
{
// details...
}
};

int main()
{
derived d{};
derived d1{d};
derived d2{std::move(d1)};
derived d3{1}; //Works!!
}


Further reading on cppreference: Using-declaration






share|improve this answer












The short answer is yes, just make them public in the base class. Inherited constructors have the same accessibility in the derived class as they do in the base. There's no way to make a private base class constructor public in the derived class.



But abstract base classes can't be instantiated on their own anyway. There's no need to make their constructors private.



CRTP has no bearing on any of the above. If you only needed it for the friend declaration, then you can do without the pattern.



class base
{
public:
base()
{
}

base(int)
{
std::cout << "base: ctor()n";
}

virtual void foo() = 0;
};

class derived: public base
{
public:
using base::base;

void foo() override
{
// details...
}
};

int main()
{
derived d{};
derived d1{d};
derived d2{std::move(d1)};
derived d3{1}; //Works!!
}


Further reading on cppreference: Using-declaration







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 23 at 3:42









Peter Ruderman

10.1k2352




10.1k2352












  • Thanks for the reply. I know that this solves the problem, but going to virtual polymorphism is not an option. The code is completely based on static polymorphism.
    – guest3450132
    Nov 23 at 9:09












  • What did you mean by "as abstract class" in the original question?
    – Peter Ruderman
    Nov 23 at 12:36












  • Abstract means, that in order to avoid misuse of the CRTP base class, it should not be instantiable without a dreived class. To prevent a wrong inheritance (a derived class that gives a wrong derived type to the CRTP) you need to make the constructors private and befriend the derived class. This way only the derived class can call the base class constructors and thus can be instantiated.
    – guest3450132
    Nov 30 at 9:21


















  • Thanks for the reply. I know that this solves the problem, but going to virtual polymorphism is not an option. The code is completely based on static polymorphism.
    – guest3450132
    Nov 23 at 9:09












  • What did you mean by "as abstract class" in the original question?
    – Peter Ruderman
    Nov 23 at 12:36












  • Abstract means, that in order to avoid misuse of the CRTP base class, it should not be instantiable without a dreived class. To prevent a wrong inheritance (a derived class that gives a wrong derived type to the CRTP) you need to make the constructors private and befriend the derived class. This way only the derived class can call the base class constructors and thus can be instantiated.
    – guest3450132
    Nov 30 at 9:21
















Thanks for the reply. I know that this solves the problem, but going to virtual polymorphism is not an option. The code is completely based on static polymorphism.
– guest3450132
Nov 23 at 9:09






Thanks for the reply. I know that this solves the problem, but going to virtual polymorphism is not an option. The code is completely based on static polymorphism.
– guest3450132
Nov 23 at 9:09














What did you mean by "as abstract class" in the original question?
– Peter Ruderman
Nov 23 at 12:36






What did you mean by "as abstract class" in the original question?
– Peter Ruderman
Nov 23 at 12:36














Abstract means, that in order to avoid misuse of the CRTP base class, it should not be instantiable without a dreived class. To prevent a wrong inheritance (a derived class that gives a wrong derived type to the CRTP) you need to make the constructors private and befriend the derived class. This way only the derived class can call the base class constructors and thus can be instantiated.
– guest3450132
Nov 30 at 9:21




Abstract means, that in order to avoid misuse of the CRTP base class, it should not be instantiable without a dreived class. To prevent a wrong inheritance (a derived class that gives a wrong derived type to the CRTP) you need to make the constructors private and befriend the derived class. This way only the derived class can call the base class constructors and thus can be instantiated.
– guest3450132
Nov 30 at 9:21


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53439372%2finheriting-private-crtp-constructor-using-friend-declaration%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks

Calculate evaluation metrics using cross_val_predict sklearn

Insert data from modal to MySQL (multiple modal on website)