How can i forward declare a class in a namespace. For example below is a header file of a library and user dont need to know about private myPtr so dont need to include boost headers when include below header file. So how can I forward declare the boost::shared_ptr to enable user code compilation?
MyClass.h
class MyClass
{
private:
boost::shared_ptr<Mytype> myPtr;
}
TL;DR The inclusion of <boost/shared_ptr.hpp> is required here. No (intelligent) way around it. MyType itself can be forward-declared though.
Of course, you can just write #include <boost/shared_ptr.hpp> at the top of your header so your users don't have to do it themselves. It's actually good practice to provide autonomous headers (ie headers that can be included first without errors).
The rules about forward compilation are slightly complicated. It is easier to understand the reason about them than to try and memorize all the cases.
There are two factors:
semantics
memory attributes (size & alignment)
Semantics: in order to access the objects' methods, attributes or base classes, you need to know about them. Seems obvious, of course, except that the constructors, assignment operators and destructors, even when automatically generated, are methods. It is easy to forget about them.
Memory attributes: unlike most languages, C++ tries to be as efficient as possible, which means that it will allocate memory for the object right there rather than allocate it somewhere and just use a pointer at the point of use, unless you instruct it to do so of course (by using either pointer or reference). In order to know how much to allocate, the compiler needs to see the guts of the object, ie what's underneath the hood. This means that even though the exact details are not accessible (private/protected stuff) they need be visible so it can see that 24 bytes aligned on a 8-bytes boundary are required (not relevant to shared_ptr by the way).
In the Standard we say the object's definition is required for either of those two needs (methods and memory layout). If the definition is required, then it must be available obviously.
Okay, now that we know the reasons, we can check various things. Is a definition needed when:
using an object as argument to sizeof or alignof? yes (obviously, memory attributes required)
using an object as attribute? yes (memory attributes required)
using an object as static attribute? no (1)
using a pointer or reference to an object as attribute? no (2)
using an object as an argument in a function declaration? no (3)
using an object as a return type in a function declaration? no (3)
passing a pointer or reference to an object around? no (4)
casting to base class? yes (semantic check of presence & accessibility of base class)
converting to another type? depends (5)
(1) the declaration does not require anything, however the definition of the static attribute will require the object's definition.
(2) a pointer is either 32 bits or 64 bits large (depending on how you compile, ...) independently of the object. A reference has an implementation-defined representation.
(3) even if taken/returned by value! It may be required for the function definition (if used within) or the function call site though.
(4) of course, should you try to use it (p->foo() or p.foo()) then it's another story.
(5) if you need to use the object's conversion operators, then it's required obviously; otherwise if you use a constructor of the other type then the same rules as for functions apply (the other type definition is required though).
I hope things are clearer now.
Related
We all know members specified protected from a base class can only be accessed from a derived class own instance. This is a feature from the Standard, and this has been discussed on Stack Overflow multiple times:
Cannot access protected member of another instance from derived type's scope
;
Why can't my object access protected members of another object defined in common base class?
And others.
But it seems possible to walk around this restriction with member pointers, as user chtz has shown me:
struct Base { protected: int value; };
struct Derived : Base
{
void f(Base const& other)
{
//int n = other.value; // error: 'int Base::value' is protected within this context
int n = other.*(&Derived::value); // ok??? why?
(void) n;
}
};
Live demo on coliru
Why is this possible, is it a wanted feature or a glitch somewhere in the implementation or the wording of the Standard?
From comments emerged another question: if Derived::f is called with an actual Base, is it undefined behaviour?
The fact that a member is not accessible using class member access expr.ref (aclass.amember) due to access control [class.access] does not make this member inaccessible using other expressions.
The expression &Derived::value (whose type is int Base::*) is perfectly standard compliant, and it designates the member value of Base. Then the expression a_base.*p where p is a pointer to a member of Base and a_base an instance of Base is also standard compliant.
So any standard compliant compiler shall make the expression other.*(&Derived::value); defined behavior: access the member value of other.
is it a hack?
In similar vein to using reinterpret_cast, this can be dangerous and may potentially be a source of hard to find bugs. But it's well formed and there's no doubt whether it should work.
To clarify the analogy: The behaviour of reinterpret_cast is also specified exactly in the standard and can be used without any UB. But reinterpret_cast circumvents the type system, and the type system is there for a reason. Similarly, this pointer to member trick is well formed according to the standard, but it circumvents the encapsulation of members, and that encapsulation (typically) exists for a reason (I say typically, since I suppose a programmer can use encapsulation frivolously).
[Is it] a glitch somewhere in the implementation or the wording of the Standard?
No, the implementation is correct. This is how the language has been specified to work.
Member function of Derived can obviously access &Derived::value, since it is a protected member of a base.
The result of that operation is a pointer to a member of Base. This can be applied to a reference to Base. Member access privileges does not apply to pointers to members: It applies only to the names of the members.
From comments emerged another question: if Derived::f is called with an actual Base, is it undefined behaviour?
Not UB. Base has the member.
Just to add to the answers and zoom in a bit on the horror I can read between your lines. If you see access specifiers as 'the law', policing you to keep you from doing 'bad things', I think you are missing the point. public, protected, private, const ... are all part of a system that is a huge plus for C++. Languages without it may have many merits but when you build large systems such things are a real asset.
Having said that: I think it's a good thing that it is possible to get around almost all the safety nets provided to you. As long as you remember that 'possible' does not mean 'good'. This is why it should never be 'easy'. But for the rest - it's up to you. You are the architect.
Years ago I could simply do this (and it may still work in certain environments):
#define private public
Very helpful for 'hostile' external header files. Good practice? What do you think? But sometimes your options are limited.
So yes, what you show is kind-of a breach in the system. But hey, what keeps you from deriving and hand out public references to the member? If horrible maintenance problems turn you on - by all means, why not?
Basically what you're doing is tricking the compiler, and this is supposed to work. I always see this kind of questions and people some times get bad results and some times it works, depending on how this converts to assembler code.
I remember seeing a case with a const keyword on a integer, but then with some trickery the guy was able to change the value and successfully circumvented the compiler's awareness. The result was: A wrong value for a simple mathematical operation. The reason is simple: Assembly in x86 does make a distinction between constants and variables, because some instructions do contain constants in their opcode. So, since the compiler believes it's a constant, it'll treat it as a constant and deal with it in an optimized way with the wrong CPU instruction, and baam, you have an error in the resulting number.
In other words: The compiler will try to enforce all the rules it can enforce, but you can probably eventually trick it, and you may or may not get wrong results based on what you're trying to do, so you better do such things only if you know what you're doing.
In your case, the pointer &Derived::value can be calculated from an object by how many bytes there are from the beginning of the class. This is basically how the compiler accesses it, so, the compiler:
Doesn't see any problem with permissions, because you're accessing value through derived at compile-time.
Can do it, because you're taking the offset in bytes in an object that has the same structure as derived (well, obviously, the base).
So, you're not violating any rules. You successfully circumvented the compilation rules. You shouldn't do it, exactly because of the reasons described in the links you attached, as it breaks OOP encapsulation, but, well, if you know what you're doing...
Is it possible to forward declare a class, and actually specify its size, such that in that same header I can use the class in a class definition?
For instance something like:
class Foo = 3 * sizeof(int);
class Bar
{
Foo foo;
};
Instead of having to #include "Foo.h", where that would be something like:
class Foo
{
int a, b, c;
};
FYI: no worries, I'd never want to do something like this (hopefully), I'm just being curious.
Note that for forward declaring enum classes the above is possible, which sounds a bit similar.
No this is not possible.
Why not?
Note that the compiler needs the complete type for instantiation an object not only for knowing the size but also to know which constructors and destructors have to be used, in your example this would only be a problem if a constructor or destructor has to be generated for Bar. There may also be alignment restrictions for Foo on a given platform.
In your case the compiler may have to generate default constructor(s) and a destructor for Bar. If Foo happens to have a non-trivial constructor and/or destructor, default or explicitly specified, that must be called in those constructors/destructors.
Comments have already mentioned that for enum classes, the complete type is in fact specified sufficiently by the forward declaration: the enum cannot have a constructor or destructor and its size and alignment restrictions are also known from the underlying integer type.
I presume the decision not to allow this was made because if class definitions could be spread around in different files, ensuring consistency would make the build process more complex and different from C. Note that C++ can be linked with rather "dumb" linkers, just like C, not actually caring about types and just filling in the right addresses for symbols (I'm simplifying a bit of course).
Not checking consistency would be very risky indeed if we could specify the size of a class in one file and then forget updating it when we add a member in another. The way it is the "one-definition-rule" says basically that anything can happen if a class has more than one non-identical definition in a program.
When studying the MySQL source code, I found some strange structs which have not any definitions. Such as the struct PSI_thread in mysql-server-code\include\mysql\psi\psi.h. But I know there must be a definition somewhere in the source code files, otherwise it couldn't be complied. Did anyone knows where is the real definition of the struct?
The definition of the struct PSI_thread
It is an opaque struct
With c, an opaque type is a structure whose content is unknown;
Usually opaques types are declared exactly as your code show, in a header:
struct PSI_thread;
typedef struct PSI_thread PSI_thread;
The code including the header will have some limitations:
You don't know the object size.
You cannot declare objects with that type directly, but you can only deal with pointers, which also means you cannot dereference them or allocate new objects.
The library (mysql in your case) provides functions to access and handle the type itself, including allocation and deallocation.
Those functions cannot simply be inline functions since they would need to access the content of the type to work.
Opaques types can be useful when you need to export the interface of a library: since you don’t know either the size or the internal ordering of an opaque type, the library can change the opaque type without changing ABI, and thus requiring a rebuild of the software using it.
You can see it as a private context of a library, used by the library to do its job safely.
EDIT
If you cannot find a forward declaration into the whole source code, you can see it as a void *. An empty struct.
The big difference is that the empty struct it is a different type compare to other possible types and compiler can complain on type mismatch.
Will it be possible to specialize std::optional for user-defined types? If not, is it too late to propose this to the standard?
My use case for this is an integer-like class that represents a value within a range. For instance, you could have an integer that lies somewhere in the range [0, 10]. Many of my applications are sensitive to even a single byte of overhead, so I would be unable to use a non-specialized std::optional due to the extra bool. However, a specialization for std::optional would be trivial for an integer that has a range smaller than its underlying type. We could simply store the value 11 in my example. This should provide no space or time overhead over a non-optional value.
Am I allowed to create this specialization in namespace std?
The general rule in 17.6.4.2.1 [namespace.std]/1 applies:
A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly
prohibited.
So I would say it's allowed.
N.B. optional will not be part of the C++14 standard, it will be included in a separate Technical Specification on library fundamentals, so there is time to change the rule if my interpretation is wrong.
If you are after a library that efficiently packs the value and the "no-value" flag into one memory location, I recommend looking at compact_optional. It does exactly this.
It does not specialize boost::optional or std::experimental::optional but it can wrap them inside, giving you a uniform interface, with optimizations where possible and a fallback to 'classical' optional where needed.
I've asked about the same thing, regarding specializing optional<bool> and optional<tribool> among other examples, to only use one byte. While the "legality" of doing such things was not under discussion, I do think that one should not, in theory, be allowed to specialize optional<T> in contrast to eg.: hash (which is explicitly allowed).
I don't have the logs with me but part of the rationale is that the interface treats access to the data as access to a pointer or reference, meaning that if you use a different data structure in the internals, some of the invariants of access might change; not to mention providing the interface with access to the data might require something like reinterpret_cast<(some_reference_type)>. Using a uint8_t to store a optional-bool, for example, would impose several extra requirements on the interface of optional<bool> that are different to the ones of optional<T>. What should the return type of operator* be, for example?
Basically, I'm guessing the idea is to avoid the whole vector<bool> fiasco again.
In your example, it might not be too bad, as the access type is still your_integer_type& (or pointer). But in that case, simply designing your integer type to allow for a "zombie" or "undetermined" value instead of relying on optional<> to do the job for you, with its extra overhead and requirements, might be the safest choice.
Make it easy to opt-in to space savings
I have decided that this is a useful thing to do, but a full specialization is a little more work than necessary (for instance, getting operator= correct).
I have posted on the Boost mailing list a way to simplify the task of specializing, especially when you only want to specialize some instantiations of a class template.
http://boost.2283326.n4.nabble.com/optional-Specializing-optional-to-save-space-td4680362.html
My current interface involves a special tag type used to 'unlock' access to particular functions. I have creatively named this type optional_tag. Only optional can construct an optional_tag. For a type to opt-in to a space-efficient representation, it needs the following member functions:
T(optional_tag) constructs an uninitialized value
initialize(optional_tag, Args && ...) constructs an object when there may be one in existence already
uninitialize(optional_tag) destroys the contained object
is_initialized(optional_tag) checks whether the object is currently in an initialized state
By always requiring the optional_tag parameter, we do not limit any function signatures. This is why, for instance, we cannot use operator bool() as the test, because the type may want that operator for other reasons.
An advantage of this over some other possible methods of implementing it is that you can make it work with any type that can naturally support such a state. It does not add any requirements such as having a move constructor.
You can see a full code implementation of the idea at
https://bitbucket.org/davidstone/bounded_integer/src/8c5e7567f0d8b3a04cc98142060a020b58b2a00f/bounded_integer/detail/optional/optional.hpp?at=default&fileviewer=file-view-default
and for a class using the specialization:
https://bitbucket.org/davidstone/bounded_integer/src/8c5e7567f0d8b3a04cc98142060a020b58b2a00f/bounded_integer/detail/class.hpp?at=default&fileviewer=file-view-default
(lines 220 through 242)
An alternative approach
This is in contrast to my previous implementation, which required users to specialize a class template. You can see the old version here:
https://bitbucket.org/davidstone/bounded_integer/src/2defec41add2079ba023c2c6d118ed8a274423c8/bounded_integer/detail/optional/optional.hpp
and
https://bitbucket.org/davidstone/bounded_integer/src/2defec41add2079ba023c2c6d118ed8a274423c8/bounded_integer/detail/optional/specialization.hpp
The problem with this approach is that it is simply more work for the user. Rather than adding four member functions, the user must go into a new namespace and specialize a template.
In practice, all specializations would have an in_place_t constructor that forwards all arguments to the underlying type. The optional_tag approach, on the other hand, can just use the underlying type's constructors directly.
In the specialize optional_storage approach, the user also has the responsibility of adding proper reference-qualified overloads of a value function. In the optional_tag approach, we already have the value so we do not have to pull it out.
optional_storage also required standardizing as part of the interface of optional two helper classes, only one of which the user is supposed to specialize (and sometimes delegate their specialization to the other).
The difference between this and compact_optional
compact_optional is a way of saying "Treat this special sentinel value as the type being not present, almost like a NaN". It requires the user to know that the type they are working with has some special sentinel. An easily specializable optional is a way of saying "My type does not need extra space to store the not present state, but that state is not a normal value." It does not require anyone to know about the optimization to take advantage of it; everyone who uses the type gets it for free.
The future
My goal is to get this first into boost::optional, and then part of the std::optional proposal. Until then, you can always use bounded::optional, although it has a few other (intentional) interface differences.
I don't see how allowing or not allowing some particular bit pattern to represent the unengaged state falls under anything the standard covers.
If you were trying to convince a library vendor to do this, it would require an implementation, exhaustive tests to show you haven't inadvertently blown any of the requirements of optional (or accidentally invoked undefined behavior) and extensive benchmarking to show this makes a notable difference in real world (and not just contrived) situations.
Of course, you can do whatever you want to your own code.
Can I use forward declaration for a class in order to put it's definition and Implementation later in the program after it's been used (similar to what is done about functions)?
(I need to join multiple source files of a program into a file, and i want to put the classes' definitions and Implementations at the end of the file in order to main be at the top of the file.)
Yes you can, to a certain extent.
You have to realize that the C++ compiler is quite stupid, and doesn't read ahead. This is the reason why you have to use function prototypes (among some other reasons).
Now, a function isn't hard for compiler to resolve. It just looks at the return type of the function, and the types of the parameters of the function, and just assumes that the function is there, without any knowledge about what's actually inside the function, because it ultimately doesn't matter at that point.
However, the contents of the class do matter (the compiler needs to know the size of the class for example). But remember about the not reading ahead bit? When you forward define a class, the compiler doesn't know about what's in it, and therefore is missing a lot of information about it. How much space does is need to reserve for example?
Therefore, you can forward define classes, but you can't use them as value types. The only thing you can do with it (before it has been concretely declared), is use pointers to it (and use it as a function return type and template argument, as pointer out by
#Cheersandhth.-Alf).
If the thing you need to use isn't a pointer, you should probably use headers (read this if you want to learn more about that).
Without a class definition somewhere earlier, you can't use any class members, nor can you create any instances, but you can
use T* and T& types,
use T for formal return type and parameter declarations (yes even by value),
use T as a template parameter,
and possibly more, but the above is what occurred to me immediately.
So if that's all you need, then you're set to go with the forward-declarations.
However, all that the forward declaring buys you in the sketched situation is added work, maintaining the same code in two places, so it's difficult to see the point of it…
Oh, I just remembered, there is a particularly nasty Undefined Behavior associated with forward-declared incomplete types, namely using delete p where p is a pointer to incomplete type. This requires the destructor to be trivial. If the compiler is good then it warns, but don't count on it.
In summary, I would just place main at the very end of that code, where it belongs, avoiding all the problems.