Inheriting private CRTP constructor using friend declaration
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
|
show 3 more comments
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
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
|
show 3 more comments
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
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
c++ using friend crtp
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
|
show 3 more comments
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
|
show 3 more comments
1 Answer
1
active
oldest
votes
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
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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
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
add a comment |
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
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
add a comment |
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
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
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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