-
Notifications
You must be signed in to change notification settings - Fork 95
feat: add map/unordered_map bounds checking #3671
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
base: develop
Are you sure you want to change the base?
Conversation
I think that the compil issue might be related to inheriting constructors |
…oveMapBoundsChecking
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it normal that there still are some direct usage of std::vector
& std::map
? (unitTests/
, event/
, fileIO/
...)
I think we will need one more PR for |
@@ -22,6 +22,7 @@ | |||
#include "xmlWrapper.hpp" | |||
|
|||
#include "common/format/StringUtilities.hpp" | |||
#include "common/StdContainerWrappers.hpp" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why adding this header here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed
string_array & phaseNames = group.getReference< string_array >( MultiFluidBase::viewKeyStruct::phaseNamesString() ); | ||
phaseNames = {"gas", "liquid"}; | ||
|
||
auto & compNames = group.getReference< string_array >( MultiFluidBase::viewKeyStruct::componentNamesString() ); | ||
string_array & compNames = group.getReference< string_array >( MultiFluidBase::viewKeyStruct::componentNamesString() ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that we found the compilation issue, I think you can revert that.
testMultiFluidBlackOil.cpp | ||
testMultiFluidCO2Brine.cpp | ||
testMultiFluidTwoPhaseCompositionalMultiphase.cpp | ||
testMultiFluidCO2Brine.cpp | ||
testMultiFluidDeadOil.cpp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
C
< T
* Access element at index with bounds checking if USE_STD_CONTAINER_BOUNDS_CHECKING is true. | ||
* Otherwise, uses operator[] for unchecked access. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Access element at index with bounds checking if USE_STD_CONTAINER_BOUNDS_CHECKING is true. | |
* Otherwise, uses operator[] for unchecked access. | |
* Access element at index with bounds checking if USE_BOUNDS_CHECKING is true. | |
* Otherwise, uses operator[] for unchecked access. | |
* @throws std::out_of_range if index is out of bounds. |
(and same below)
template< typename TKEY, typename TVAL, typename SORTED > | ||
class mapBase | ||
{}; | ||
|
||
/// @cond DO_NOT_DOCUMENT | ||
template< typename TKEY, typename TVAL > | ||
class mapBase< TKEY, TVAL, std::integral_constant< bool, true > > : public stdMap< TKEY, TVAL > | ||
{ | ||
public: | ||
using stdMap< TKEY, TVAL >::stdMap; | ||
}; | ||
|
||
template< typename TKEY, typename TVAL > | ||
class mapBase< TKEY, TVAL, std::integral_constant< bool, false > > : public stdUnorderedMap< TKEY, TVAL > | ||
{ | ||
using stdUnorderedMap< TKEY, TVAL >::stdUnorderedMap; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we could simplify this part:
- about the
mapBase
naming, there is no real "base" concept here, nor need for a class here, - why not simplifying the
std::integral_constant
to a simplebool
? - a pattern like the
std::*_t
would be more standard.
I would suggest:
namespace internal
{
template< typename TKEY, typename TVAL, bool SORTED >
struct stdMapTypeDefinition
{};
template<typename TKEY, typename TVAL>
struct stdMapTypeDefinition< TKEY, TVAL,true >
{ using Type = stdMap< TKEY, TVAL >; };
template<typename TKEY, typename TVAL>
struct stdMapTypeDefinition< TKEY, TVAL,false >
{ using Type = stdUnorderedMap< TKEY, TVAL >; };
} // namespace internal
/**
* @brief templated type for ordered and unordered maps.
* @tparam TKEY key type
* @tparam TVAL value type
* @tparam SORTED a bool indicating whether map is ordered
*/
template< typename TKEY, typename TVAL, bool SORTED >
using stdMapType = internal::stdMapTypeDefinition<TKEY,TVAL,SORTED>::Type;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They would be a lot of changements in BufferOps.hpp imo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I renamed mapBase
to mapType
I can't change typename SORTED
to bool SORTED
, I tried and it required a lot of work for this PR and maybe when we will jump into c++20 for concepts
template< typename MapType, | ||
bool USE_BOUNDS_CHECKING = false | ||
> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
template< typename MapType, | |
bool USE_BOUNDS_CHECKING = false | |
> | |
template< typename MapType, | |
bool USE_BOUNDS_CHECKING = false > |
// Override operator[] | ||
MappedType & operator[]( KeyType const & key ) | ||
{ | ||
if constexpr (USE_BOUNDS_CHECKING) | ||
{ | ||
return this->at( key ); // Throws std::out_of_range if key is missing | ||
} | ||
else | ||
{ | ||
return Base::operator[]( key ); // Inserts default-constructed value if missing | ||
} | ||
} | ||
|
||
MappedType const & operator[]( KeyType const & key ) const | ||
{ | ||
if constexpr (USE_BOUNDS_CHECKING) | ||
{ | ||
return this->at( key ); | ||
} | ||
else | ||
{ | ||
return Base::operator[]( key ); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where the behaviour of these operators is tested in fonction of all possible USE_BOUNDS_CHECKING
values? (same remark for stdVector
, except that it cannot be tested against USE_BOUNDS_CHECKING=false
)
If they are not tested, we can add them in testDataTypes.cpp
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a test in testDataTypes.cpp
@arng40 Do you think it would be good idea to introduce the aliases (i.e. stdUnorderedMap, stdMap) in a separate PR which just aliases to std::unordered_map, and std::map so that we can review the actual changes independently from this swap...which should result in no behavioral changes with develop? |
@rrsettgast |
This PR adds further bounds checking in GEOS.
the new wrappers are preprocessor guarded with aliases s.t. they alias to the std::container in the non-bounds checking case.