std::basic_ios has a public constructor:
explicit basic_ios (std::basic_streambuf<CharT,Traits>* sb);
IMO, the sole reason for a class to have a public constructor is to use a standalone instance of that class in a program. If a class exists only to have other classes descend from it (as seems to be the case for basic_ios), all of the class's constructors should be protected. The constructors of std::ios_base are all protected. But, for some reason, the designers of the standard made this one constructor of basic_ios public.
basic_ios is used as a base class for several stream types, and I can't envision a use case where you'd have one that wasn't at least a basic_istream or basic_ostream. Is there one?
The other reason for a class to have a public constructor is to have this constructor signature available to construct a derived object:
struct B{
B(int);
protected:
~B();
};
struct A:B{
private://no effect.
using B::B;
public:
A(void*);
};
A a(10);
The constructor must be public in the base class because a using declaration of a base constructor does not change the accessibility of the inherited constructor.
What I failed to notice was that std::basic_istream, std::basic_ostream and std::basic_iostream also had public constructors (each takes a std::basic_streambuf*).
This allows for a generic-programming analogue of polymorphism, in the same vein as the pimpl idiom.
That is, this way you can create a specialized streambuf type and use it in a basic_[io]stream without having to create specialized stream classes. (The functionality is limited: You can't assign a new buffer to the same stream, and you have to externally keep track of the buffer's lifetime and ownership).
The specialized basic_[io]fstream and basic_[io]stringstream each contain a full instance of the associated buffer type. This means an instance of a specialized stream type will only work with its internal buffer and not another, not even one of the same type. Using a raw basic_[io]stream is a (clunky) workaround to this.
template<class C, class TR>
class snazzy_filebuf: public std::basic_streambuf<C, TR>
{
protected:
typename TR::int_type overflow(TR::int_type) override;
typename TR::int_type underflow(TR::int_type) override;
typename TR::int_type pbackfail(TR::int_type) override;
public:
snazzy_filebuf();
};
.....
snazzy_filebuf<char> buf;
std::basic_ostream<char> o_s(&buf);
o_s << "Hello, world\n";
Related
so I am trying to construct a class with helper method, namely:
class Type{
int a, b, c;
friend auto helper(auto);
friend auto test_helper(auto);
/* couples test with implement */
public:
void method(){
helper(this);
}
};
But making helper a friend function couples the test with implementation if we want to test helper.
So I want to make helper a free function, namely:
auto helper(int&,int&,int&);
auto test_helper(int&,int&,int&);
class Type{
int a, b, c;
public:
void method(){
helper(a,b,c);
}
};
This, however, makes the code a lot more tedious when data members are many. So, I came up with an idea to construct an helper struct that has exact data member as Type but with all data member being public, so that we'll be able to simply pass in the handle of such HelperType, maybe something like:
struct HelperType{
int a, b, c;
};
auto helper(HelperType* a);
auto test_helper(HelperType* a);
void Type::method(){
helper(static_cast<HelperType*>(this));
}
Is there any elegant approaches to construct such HelperType struct? Such as a generic wrapper or perhaps with inheritance?
I have no simple solution to create HelperType from Type (only things coming to mind involve heavy metaprogramming or macro usage). However building Type from HelperType would be quite trivial, using private inheritance. From Derived class (cppreference.com):
When a class uses private member access specifier to derive from a base, all public and protected members of the base class are accessible as private members of the derived class.
// Could be renamed "TypePrivateMembers" or "TypeData"
struct HelperType{
int a, b, c;
};
auto helper(HelperType* a);
class Type : private HelperType {
public:
// a,b,c can be accessed in Type class scope.
void method(){
helper(this);
}
};
Live demo
However, still from cppreference (emphasis mine):
Private inheritance can also be used to implement the composition relationship (the base class subobject is an implementation detail of the derived class object). Using a member offers better encapsulation and is generally preferred unless the derived class requires access to protected members (including constructors) of the base, needs to override a virtual member of the base, needs the base to be constructed before and destructed after some other base subobject, needs to share a virtual base or needs to control the construction of a virtual base. [...]
This is the recurring composition over inheritance debate. This question has already been asked many times on StackOverflow, here are a few interesting link on the topic (in general & for this specific case):
Prefer composition over inheritance ? (language agnostic)
When to use C++ private inheritance over composition?
I'm having trouble understanding why my template hierarchy won't pass constructor arguments deeper than one layer.
So far I've read that it may have something to do with namespacing or template constructors being unnamed. My various attempts at getting the constructor arguments through to the base class with scoping directives have failed.
// test.cc
#include <string>
// Base class, obviously.
template <typename T>
class Base {
public:
Base(const T& t) : _t(t) {}
virtual ~Base() { }
virtual T getVal() const { return _t; }
private:
T _t;
};
// First derivation. This works, although it is explicit.
class DerivedOne : public virtual Base<std::string>
{
public:
DerivedOne(const std::string& path) : Base<std::string>(path) {}
virtual ~DerivedOne() {}
};
// Second derivation. Constructor fails to compile unless I explicitly
// pass the 'path' argument to Base in the initializer list or create a
// default constructor for Base (which, of course, leaves Base::_t
// uninitialized).
class DerivedTwo : public virtual DerivedOne
{
public:
DerivedTwo(const std::string& path) : DerivedOne(path) {}
// This works
// DerivedTwo(const std::string& path) : DerivedOne(path), Base(path) {}
virtual ~DerivedTwo() {}
};
int main()
{
return 0;
}
The compiler complains:
test.cc: In constructor ‘DerivedTwo::DerivedTwo(const string&)’:
test.cc:31:58: error: no matching function for call to ‘Base<std::__cxx11::basic_string<char> >::Base()’
DerivedTwo(const std::string& path) : DerivedOne(path) {}
^
test.cc:7:5: note: candidate: Base<T>::Base(const T&) [with T = std::__cxx11::basic_string<char>]
Base(const T& t) : _t(t) {}
^
test.cc:7:5: note: candidate expects 1 argument, 0 provided
test.cc:5:7: note: candidate: Base<std::__cxx11::basic_string<char> >::Base(const Base<std::__cxx11::basic_string<char> >&)
class Base {
^
test.cc:5:7: note: candidate expects 1 argument, 0 provided
Why do I need to declare a default constructor when it seems that the parameterized constructor should be called? Why must I explicitly pass DerivedTwo's parameter to Base, since I've passed it to DerivedOne (who should pass it to Base)?
Is there some way to avoid this duplication? Does this mean I can't use initializer lists when a base template constructor parameter is allocated on the heap in a derived class initializer list?
What is going on
When you inherit virtually, you are asking that the type you inherit from is a "singleton" within the object heiarchy (not a program-wide singleton, but a instance-wide singleton, strange as that may seem).
As a side effect, the actual most derived class is responsible for constructing the virtual base class, regardless of what intermediate classes exist.
Virtual inheritance is intended when you need to inherit from some class more than once, yet ensure that only one instance exists. Rather than work out some complex set of rules to determine whose constructor call would be the one to be called, the designers of C++ mandated that the most-derived class (the actual one being created) dictates exactly what constructor is called.
Everyone else can chime in, but only if an actual instance of that specific class (and not a more-derived one) is created does their opinion matter.
You probably don't want virtual there
virtual inheritance has almost nothing to do with virtual methods/member functions. Don't use it unless you need to for binary layout or diamond inheritance reasons.
Simply eliminate it from your code, and if you never inherit from a class along 2 different paths to the same most-derived class, you won't miss it.
class DerivedOne : public Base<std::string>
and
class DerivedTwo : public DerivedOne
and your code compiles and does what you seem to want.
When you use virtual inheritance it is always the MOST DERIVED class that initializes the virtual base. Even though your intermediate class passes a value up, it won't do that in further derived classes, which must directly initialize Base.
Since your most derived class (DerivedTwo) doesn't directly initialize Base, then Base is initialized without any parameters passed to it, and so requires a default constructor.
class DerivedTwo : public virtual DerivedOne
{
public:
DerivedTwo(const std::string& path) : Base(path), DerivedOne(path) {}
}
Alternately, stop using virtual inheritance, and just use "normal" inheritance. That is, change this:
class DerivedOne : public virtual Base<std::string>
to this:
class DerivedOne : public Base<std::string>
Unless, of course, you really need virtual inheritance. :)
So a base class has multiple constructors:
sf::Sprite()
sf::Sprite(const Texture& texture)
sf::Sprite(const Texture& texture, const IntRect& rectangle)
And I'm subclassing this class multiple times:
class Sub : public sf::Sprite {
public:
Sub() : sf::Sprite() {};
Sub(const Texture& texture) : sf::Sprite(texture) {};
Sub(const Texture& texture, const IntRect& rectangle) : sf::Sprite(texture, rectangle) {};
// My subclass specific code
};
As you see, I have to repeat these three constructors for every subclass. Is there a way to avoid this, since the constructors usually don't do anything special? Sometimes I need some class specific initialization though, so it's not always viable to just straight out copy everything.
You can accomplish this by inheriting constructors (since C++11).
If the using-declaration refers to a constructor of a direct base of the class being defined (e.g. using Base::Base;), all constructors of that base (ignoring member access) are made visible to overload resolution when initializing the derived class.
e.g.
class Sub : public sf::Sprite {
public:
using sf::Sprite::Sprite;
// My subclass specific code
};
If the inherited constructors is used to initialize a Sub, the sf::Sprite subobject is initialized using the inherited constructor, and all other members of Sub are initialized as if by the defaulted default constructor.
If there're some special cases need to be processed, you still can define constructor(s) in Sub, the inherited constructor with the same signature will be hidden.
As with using-declarations for any other non-static member functions, if an inherited constructor matches the signature of one of the constructors of Derived, it is hidden from lookup by the version found in Derived.
You can use the using keyword to inherit the constructor of your base class, excluding the special ones (default, copy, move). To shorten your default constructor simply use = default. If you want class specific initialization you can simply write the constructor again, just as you do now.
class Sub : public sf::Sprite {
public:
Sub() = default;
using sf::Sprite::Sprite;
Sub(const Texture& texture)
{
// your custom code.
};
// My subclass specific code
};
If you can just 'inherit' the constructor, i.e. have one with exactly the same arguments, simply use using as explained in the other answers. However, if your derived class's constructor has additional arguments and/or requires some class specific initialization, you may use a variadic template.
struct base
{
base(int);
base(std::string const&);
base(some_type const&);
base(std::string const&, some_type const&);
/* ... */
};
struct derived : base
{
template<typename...Args>
derived(some_other_type const&x, Args&&...args)
: base(std::forward<Args>(args)...)
, private_datum(x)
{
construction_details(); // class-specific initialisation
}
private:
some_other_type private_datum;
void construction_details(); // implemented in source code
};
I'm trying to publicly derive a class from a template that will make it inherit from a base class and get access on protected members. But before the template is expanded it doesn't have those rights, so it can't use a Base member as a template parameter:
using Fun = void (*)();
class Base {
protected:
// friend class Derived; // ...need this to eliminate complaint
static void something();
};
template<Fun F>
class Variant : public Base {};
class Derived : public Variant<&Base::something> { // `something()` is protected
public:
void somethingElse() {
something(); // doesn't complain about this `something()`
}
};
int main() {}
The weird bit about this to me was that friending it worked at all. I wondered if I might "sneak Derived in the door" by putting a public virtual inheritance from Base before the Variant:
class Derived : public virtual Base, public Variant<&Base::something>
That didn't help.
Question: is there some other trick for avoiding explicit mention of all derived classes in Base, yet still have access to pick protected members out of it for template parameters?
(Note: Trying this on an older gcc, 4.6.3, looks like even the friending doesn't help in that case. So it seems support for that is somewhat new.)
Stick the offending access into a metafunction. Derive the metafunction class from the base.
template<typename B>
struct something_variant : public B {
typedef Variant< & B::something > type;
};
class Derived : public something_variant<Base>::type {
…
http://coliru.stacked-crooked.com/a/6bca00455bd3daca
Regarding CWG 372, the critical text in the resolution is this:
[A]ccess checking of base-specifiers must be deferred until the entire base-specifier-list has been seen.
This was already accepted in C++11, so it's interesting that your example is rejected. And, plugging the relevant example code from the C++11 standard into recent Clang and GCC demonstrates that they simply did not implement the deferral. It's at least a little unsurprising, since implementation requires some data structure to represent a set of deferred access checks… fairly high effort for a corner case.
I have the following base template class.
template<typename T>
class Base {
public:
void do_something() {
}
};
It is intended to be used as a curiously recurring template pattern. It should be inherited like class B : public Base<B>. It must not be inherited like class B : public Base<SomeoneElse>. I want to statically enforce this requirement. If someone uses this wrong, I expect an error in the compiling phase.
What I'm doing is putting a static_cast<T const&>(*this) in do_something(). This way the class inheriting the template is or inherits from the class provided as the template parameter. Sorry for the confusing expression. In plain English, it requires B is or inherits from SomeoneElse in class B : public Base<SomeoneElse>.
I don't know if it's the optimal way to achieve this. Looks gross to me.
However I want to do more. I want to ensure B is SomeoneElse itself. How can I do that?
Make the constructor (or destructor) of Base private, and then make T a friend. This way the only thing that can construct/destruct a Base<T> is a T.
If your class contains some code that says:
T* pT = 0;
Base *pB = pT;
Then there will be a compiler error if T is not assignment-compatible with Base.
This kind of check is formalised in C++11 so you don't have to write it by hand and can get helpful error messages:
#include <type_traits>
template<typename T>
class Base {
public:
void do_something()
{
static_assert(
std::is_base_of<Base, T>::value,
"T must be derived from Base");
}
};
class B : public Base<B> { };
int main()
{
B b;
b.do_something();
}
As to ensuring that Base's type parameter is exactly the class that is deriving from it, that seems conceptually flawed. A class that is acting as a base class can't "talk about" the type that is inheriting it. It may be inherited more than once via multiple inheritance, or not at all.
Two good answers so far. Here is another which uses the idiom of generating custom access keys to certain methods (in this case a constructor). It provides an absolute guarantee of correct use while not exposing private methods in the base to the derived.
It can also be used to control access to other methods in the base class on a case-by-case basis.
template<class Derived>
struct Base
{
private:
// make constructor private
Base() = default;
protected:
// This key is protected - so visible only to derived classes
class creation_key{
// declare as friend to the derived class
friend Derived;
// make constructor private - only the Derived may create a key
creation_key() = default;
};
// allow derived class to construct me with a key
Base(creation_key)
{}
// other methods available to the derived class go here
private:
// the rest of this class is private, even to the derived class
// (good encapsulation)
};
struct D1 : Base<D1>
{
// provide the key
D1()
: Base<D1>(creation_key())
{}
};