I have a use case where I need to use counting_semaphore as a data member in a class. If it were a global variable, I could've omitted the template argument, and it would've been default initialized. But as mentioned here, in case of a member variable, the template argument needs to be specified, and in our case it has to be a compile-time constant.
So, I'm not sure what to initalize the value of LeastMaxValue to? Are there any heuristics for it that you use, or is there a way I can still use the implementation defined default value for this?
Ideally, you would look at how the data member will be used and determine an upper bound on what the semaphore needs to count. This upper bound is an appropriate LeastMaxValue.
It is not always possible to find such a bound, though. If you have no way of bounding the maximum the data member needs to handle, you could use the largest possible value, std::numeric_limits<std::ptrdiff_t>::max().
Related
Let's say we have a variable
std::optional<T> x;
of type std::optional<T> for some type T.
If I want to call a constructor of T inside x and initialize it, I can call the member function std::optional::emplace. As I know, this member function checks if the instance already exists (that is, bool(x) evaluates to true), and if that's the case, it first destroys the previously constructed instance and then re-initialize it using the constructor and arguments provided.
I'm wondering if it is possible to do only initialization w/o this checking and destruction. When dealing with std::optional, it seems quite common to first check if the instance exists and then do some separate works depending on the result. Therefore, it seems reasonable to argue that quite often when we need to emplace an instance inside std::optional, we already know that it does not contain any initialized instance. Hence, it seems reasonable to provide an "unsafe-version" of std::optional::emplace that does not check and destroy the previous instance, but std::optional does not have such a member function. Is there any way to accomplish this?
Perhaps, if there are some guarantees about memory layout for std::optional (which I guess not), then I can call placement new operator directly...
No, it's not possible. And no, calling placement new directly onto the memory wouldn't help either since you'd also have to set the flag in the optional indicating that the optional is engaged - and you can't do that externally.
Therefore, it seems reasonable to argue that quite often when we need to emplace an instance inside std::optional, we already know that it does not contain any initialized instance
That's not a strong argument. emplace() is simply a potential optimization on top of operator=, there's no implicit hint in the use of such a function about the current state of the optional.
Also, if your code is structured like:
if (!o) {
// stuff
o.emplace(some, args, here);
}
You can rest assured that your compiler will see the duplicate branch between the explicit operator bool() check and the internal emplace() check and collapse them together, so there will not be an extra branch.
Is there any way to assign a pointer-to-class-member so that it points to the class itself?
This would effectively mean that the result of applying the member pointer to an instance of the class would be a reference to that very same instance.
eg:
struct SFoo {};
constexpr SFoo SFoo::* MP_foo = &SFoo:: MYSELF;
// Is there some syntax I can use here? --^
The reason I want this is I have a sorting algorithm that works on a container of elements of an arbitrary template type. The sorting key is obtained from each element using a supplied pointer-to-member.
However, I now wish to sort a container where the element is also the key. Thus, I need to make the member-pointer point to itself (as if the class were its own member).
There are a number of easy (and zero cost) hacks I can use (and I'm using one now), but I want to know if there's some syntactical trick I can use to get it done the right way - to avoid extra inelegant code.
Unfortunately the question is not very clear (but -1 is not mine). My impression is that you are confusing the type of the object that is to be sorted (in your case this is SFoo), and the type of the sorting key. In a typical situation they are different. Ex: Users to be sorted (object) and the sorting key is the first and the last name (a pair of strings). You are not stating the type of the sorting key directly.
Syntactically SFoo SFoo::* MP_foo is a pointer to the instance field whose type is SFoo. C++ does not allow that because otherwise this will cause infinite recursion. This field will have SFoo filed and that inner field will need to have this field again.
Second, you are trying to initialize pointer to a data with the pointer to a function. Constructor SFoo::SFoo is a function. And as it is mentioned in comments, the addresses of ctors are not allowed.
One more attempt: Applying the member pointer to an instance of the class would be a reference to that very same instance.
Pointer to member points to a member. The object is not its member. Good or bad this is how C++ is defined.
You might try to define a wrapper class, something like:
struct SFoo2
{
SFoo m_data_field;
};
Note that from the point of view of memory layout they will be identical. SFoo2 can have pointer to member of type SFoo. I am not sure if this will work in your context, but you may give it a try.
This question already has answers here:
C++: Is it better to pass an enum as a value or as a const reference?
(5 answers)
Closed 7 years ago.
Correct my if I'm wrong, but the reason you pass integers and other basic data types by value is because the memory they occupy is too small, so it's a waste to make a pointer variable of that data type (which will probably be at least the same size as the data type).
That's why I always pass ints and other basic types by value to functions, and other (bigger) data types are passed by const references or by pointers of const. Did I grasp this right?
Now I've seen many APIs that pass enum types as const references, like so:
enum FileOptions { ReadOnly, ReadWrite, WriteOnly };
void processFile(const FileOptions &options);
As far as I know, enums are usually interpreted by the compiler as plain integers, so why are they passed by references? Is it done to abstract the data type from the developer, so he won't think of FileOptions as an integer? (although it is).
The only advantage I can see is, that if you later decide to create a class with extended funcitonality, you can pass it still efficiently without changing the code everwhere.
Any decent optimizer doesn't care for the reference if it is a const reference for a base type anyway, and creates the same code in both cases.
Another consequence could be if the reference is to some other variable and it is changed by another thread, it can even change it's value during the course of your function (even though it says it's const) which, I would think, is not really desireably. In this case it would heavily depend on the optimization what value is used in a given branch of that method.
You are right, the enum is basically a 'const int'.
Second guessing why some developer chose a certain style is futile.
Unless you call the function in a very close loop it doesn't matter anyhow.
In modern C++ there is also enum class which is strongly typed enums.
I think const reference is used only for similarity and easy to modificate in future.
For example you have a class with a lot of methods, all parameters in this methods usually complex objects and of course passed by const reference. So you declare the enum parameter in the same way. And you will know for sure that it's should not be changed and so on
Later you may deside to convert enum in more complex object, and you will no need to update function declaration at all. It's already suitable for such refactoring
There is one big difference: If you pass options as a value, then it becomes a local variable in your function, and only your function can change it. If you pass options as a const&, then there is a variable somewhere, which might be a static or global variable, and if your function modifies any other variable of type FileOptions, then it might be the one that was passed to you as a const&, so the value of options might change.
And if your function calls another function, then that function might change the variable behind options. So as a developer, after any function call you could suspect that options might have changed (although if that happens, that would be about the worst possible programming style imaginable), but also the compiler would have to assume that it has changed unless it can prove otherwise.
Modifying a const& in that way would be awful, so we can safely assume that unless the caller absolutely hates you a const& won't be changed. You use const& when you actually want to pass a value, but passing it by reference seems to be more efficient. For an int that is pointless, for an array containing ten megabytes worth of int's it's not at all pointless.
Another use for const& instead of value is for objects that cannot easily be copied. For example a mutex cannot easily be copied. Or an object giving exclusive access to a file can by definition not be copied in a meaningful way.
Given a variable taken from a vector, is there a way to identify the type.
Note that I already know the type of member and can specify it in the call to a template. This is a specific vector that allows a push_back() of particular types of variables.
For example, we have a class that allows a vector operation.
auto data = member().back(); // gets the last entry in the member vector
Using a template, I want to create a new entry of the type
dataType newdata;
member().push_back(newdata)
Is there a way of identifying what dataType is, given the result of the back() operation? If there is, I can create a Template, and retrieve the type by passing in the member indicator.
If not, I would have to pass in the type specifically in order to define
::base::dataArea newdata;
You can just use typename std::remove_reference<decltype( member().back() )>::type if you really want to be clever. But instead you should use typename V::value_type, where V is the type of the vector accessed via member. See e.g. the docs at cppreference: it's often a good idea to consult the relevant documentation.
Simple solution: member().resize(member().size()+1).
You cannot reason about unknown datatypes in general, so there is very little what you can do with them. You can't blindly assume they have a member .foo() for instance. You might reasonably assume that the type has a default, copy and/or move constructor, and then you often don't need to spell out the type either - as shown in the .resize() call.
In my class I was using such field:
private:
bool firstSeqNumReceived;
Everything were working fine for a while but after one commit I've figured out that now field is true by default. Surprisingly field is not initialized to false by default, instead assigned value is implementation dependent (refer to What is the default value for C++ class members for more details )
Now I wonder why compiler doesn't produce compile-time error forcing me to add initialization?
Who needs "implementation-dependent" default value, are there any use-cases? Why not produce compile-time error in this case?
I wonder why compiler doesn't produce compile-time error forcing me
to add initialization?
Because the compiler assumes you know what you're doing.
In C++ you don't pay for what you don't use. There may be use cases where initialization is a waste of time. For example, in a class where real meaningful values for members cannot possibly be computed until after the object has been constructed, initializing the members to some default or sentinel value accomplishes little.
The use-case is basically, that it depends on the program flow if you are using the variable or not. If you don't use it in parts of your code then there is also no need to zero initialise it.
Also if you know, that the value will be assigned in the constructor or some other member function it would be just a superfluous step to first write 0 into memory.
The standard specifies that it is undefined behaviour to access an uninitialized object. There are a few reasons such undefined behaviour appears in the standard. This one is more about not giving you more than you ask for. Sometimes you really don't want to initialize a variable as soon as you create it. Instead, the compiler trusts you to initialize an object when you need it initialized. As an example of when you don't want it initialized automatically:
int x;
std::cin >> x;
It would be completely pointless to automatically initialize x to 0 as the value is immediately overwritten. The power to initialize a variable is in your capable hands.
Compilers may also assume you do not invoke undefined behaviour in order to make optimizations.