-
Notifications
You must be signed in to change notification settings - Fork 296
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
Modernization/keywords #1183
base: master
Are you sure you want to change the base?
Modernization/keywords #1183
Conversation
self documenting addInputKeyword and mking the types public applied the example to dumpforces making the enum bitmask makes everithing compile :D reworking "add" reserve and use
I noticed that this changes the way components are registered and I am wondering if there's an impact on LOADed source files. Is the "old" way to specify the type of component still working after this change? |
/** | ||
@brief Test if an enum value is valid. | ||
|
||
@param a The enum value to test. | ||
@return true if the enum value is not equal to zero, false otherwise. | ||
|
||
|
||
This operator is only available for enum types that have a specialization of | ||
enum_traits::BitmaskEnum with the `has_valid` trait enabled. | ||
|
||
@code | ||
// Note: explicit declarations of the values, and | ||
enum class myenum { A=1,B=1<<1,C=1<<2 }; | ||
//then activate the functions `&`, `|` and `valid` | ||
template<> | ||
struct BitmaskEnum< myenum > { | ||
static constexpr bool has_valid = true; | ||
static constexpr bool has_bit_or = true; | ||
static constexpr bool has_bit_and = true; | ||
}; | ||
//...code... | ||
myenum val = myenum::A | myenum::C; | ||
std::cout <<"val is "<< int(val) << "\n"; | ||
if(PLMD::valid( val & myenum::A)) { | ||
std::cout << "val has A\n"; | ||
} | ||
if(PLMD::valid(val & myenum::B)) { | ||
std::cout << "val has B\n"; | ||
} | ||
if(PLMD::valid(val & myenum::C)) { | ||
std::cout << "val has C\n"; | ||
} | ||
if(PLMD::valid(val & (myenum::A | myenum::C))) { | ||
std::cout << "val has C and A\n"; | ||
} | ||
//will produce: | ||
///>val is 5 | ||
///>val has A | ||
///>val has C | ||
///>val has C and A | ||
@endcode | ||
|
||
@see operator|(enumtype, enumtype) | ||
@see operator&(enumtype, enumtype) | ||
*/ |
Check notice
Code scanning / CodeQL
Commented-out code Note
//plumed_assert( ckey.find(cnames[i])->second=="default" ); | ||
if( ckey.find(cnames[i])->second!="default" ) { | ||
for(const auto& cname : cnames) { | ||
//plumed_assert( components.at(cname).key=="default" ); |
Check notice
Code scanning / CodeQL
Commented-out code Note
bool Keywords::getLogicalDefault(const std::string & key, bool& def ) const { | ||
if( booldefs.find(key)!=booldefs.end() ) { | ||
def=booldefs.find(key)->second; | ||
// plumed_massert(exists(key)||reserved(key),"You can't ask for the default value of a keyword that doesn't exist("+key+")"); |
Check notice
Code scanning / CodeQL
Commented-out code Note
I left the old functions that accepts strings, on that point the API is not changed but grown with the function that get the enums. I only changed two files to give an idea on how it is possible to do that I think I also maintained the same order of the old version when querying components and kws. Is that what you were asking? A thing that is changed behind the curtains is
that now tests for |
Description
I slightly compacted Keywords, and I think it makes easier maintain the keywords:
Before, for the keywords you had an hashmap for the type, one for the docstring, one for the allowmultiple option, one for the argument type, one for the atom tag specialization,one for the default value and one for the default values for the flags.
Now all of these have been compacted in a single hashmap that contain a struct with all the necessary info, that I think makes far more easier to work with this and maintain it.
Same thing has been done for the components.
This should also occupy less space, since we do not have to store all the N sets of keys but only one (plus an extra vector for keeping the order of declaration and ease the reserved/declared keyword logic).
Now adding a new functionality for the keywords or the components will mean not book-keep another hashmap (and update the signature of
copyData
) around the various function that add/remove components and keywords, but simply updating the existing struct and managing the presence of that functionality where it is neededSome other things done here:
I removed the
get()
method, since was a double ofgetKeyword()
and the latter was more self-documenting.I removed the friend declarations, most of them where not needed since Keywords has alredy the needed getters method, and in other cases like
isActionSuffixed()
andisActionNeeded()
that logic should be inside Keywords and not in other places.void setDisplayName( const std::string& name );
in theActioRegister
as I did? That function does exactly what the friend access did before.See how
void copyData( std::vector<std::string>& kk, std::vector<std::string>& rk, std::map<std::string,KeyType>& tt, std::map<std::string,bool>& am, std::map<std::string,std::string>& docs, std::map<std::string,bool>& bools, std::map<std::string,std::string>& nums, std::map<std::string,std::string>& atags, std::vector<std::string>& cnam, std::map<std::string,std::string>& ck, std::map<std::string,std::string>& cd ) const ;
has been compacted intovoid add( const Keywords& keys );
Apart from the few now no more friend files, I also modified two files as an example:
DumpForces.cpp
andDistance.cpp
with an example of the usage of the enums outside in the code, In my opinion this can avoid errors due to typos, so that the compiler will help.removeOutputComponent
andremoveComponent
do circa the same thing in the original, both remove the name of the component, butremoveComponent
removes also the component related keyword and checks for existence of the queried component, both did not remove the component type. Is this a undocumented wanted behavior?(Also I do not understand why the all the searches here were embedded in
while(true){}
loops)Using the diff interface the difference between the old version of the functions is:
I maintained the
throw/not throw
behavior. But all the component-related data is removed in both cases.On a secondary note I set up (taking a lot of "inspiration" here and there) also a way of using enums as named bitmask without getting too much crazy. I think this can also be useful elsewhere
I also tried to move something to string_view, but I found out that is not always a good idea.
Note that I did not changed the fix i proposed in #1168 is not applied here
Target release
I would like my code to appear in release 2.11, but maybe I can back port a version into v2.10 it needs some modifications
Type of contribution
Copyright
COPYRIGHT
file with the correct license information. Code should be released under an open source license. I also used the commandcd src && ./header.sh mymodulename
in order to make sure the headers of the module are correct.Tests