Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better default ctor for MGLevelObject #16979

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

RichardYCJ
Copy link
Contributor

close #16978

*/
MGLevelObject(const unsigned int minlevel = 0,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since no argument is equivalent to template <> of the previous ctor, the only usage of this function is for default construction.

@peterrum
Copy link
Member

peterrum commented May 8, 2024

The general issue is that MGLevelObject assumes that there at least one level. See for example:

template <class Object>
unsigned int
MGLevelObject<Object>::max_level() const
{
return minlevel + objects.size() - 1;
}

which will now return -1 with the result that other function that use that are not well defined anymore.

Having the possibility to have an empty MGLevelObject would be great (and I thought about that already in the past as I was confused that there is always at least one level), but we will need to go through each function to check if this does not introduce some unwanted side effects.

@RichardYCJ
Copy link
Contributor Author

RichardYCJ commented May 8, 2024

The general issue is that MGLevelObject assumes that there at least one level.

@peterrum Yeah you are right! And does this one level object have to be initialized? I mean does the objects[0] (which is a shared_ptr) must not be nullptr?

If not, I can call object.resize(1) inside the default ctor.

@peterrum
Copy link
Member

peterrum commented May 8, 2024

If not, I can call object.resize(1) inside the default ctor.

I am not sure if it is a good idea to have a dummy entry in the vector just to make the rest of the code working. Generally, the issue is that we store inclusive ranges [min_level, max_level] and not exclusive ones [min_level, max_level + 1[. This is why we always write loops like:

for (unsigned int l = min_level; l <= max_level; ++l)

Personally, I would probably go with the solution to keep the internal vector empty (as suggested in this PR) and add asserts to other functions that indicate that they don't make sense if there are no levels...

But let's wait for the opinion of someone else who knows the historical background of this class.

@bangerth
Copy link
Member

bangerth commented May 8, 2024

For one, max_level() defined as

template <class Object> 
 unsigned int 
 MGLevelObject<Object>::max_level() const 
 { 
   return minlevel + objects.size() - 1; 
 } 

will no longer be able to return an unsigned int. I would think that is at least surprising.

What kind of object do you have that cannot have a default constructor? In order to use the MGLevelObject later, you will have to reinit it to a nonzero size. In that case, if the stored type does not have a default constructor, what does reinit() do?

@RichardYCJ
Copy link
Contributor Author

What kind of object do you have that cannot have a default constructor? In order to use the MGLevelObject later, you will have to reinit it to a nonzero size. In that case, if the stored type does not have a default constructor, what does reinit() do?

@bangerth reinit actually have variadic template parameter that can pass parameter in. I need the default ctor to let some class (that holds resources) to be default constructable. It will be reinit after like during setup_system.

@RichardYCJ
Copy link
Contributor Author

Hi @peterrum, seems not much attention to this :-(

Maybe I can try adding reinit and see if it can pass the tests?

My argument is that users who use default ctor will, in most cases, reinit it to the MG level after like setup_system. And for those who just want a one level default constructable T, they can use MGLevelObject<T>(0, 0).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

MGLevelObject prevents default construct
3 participants