-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
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
[filters] Create a SamplingFilter base class #3724
Comments
I don't believe this to be a good first issue. There's some knowledge of the API that needs to be taken into account. |
Here's my current prototype. Relevant things to mention:
namespace pcl
{
template<typename PointT, typename RandomEngineT = std::default_random_engine>
class SamplingFilter : public FilterIndices<PointT>
{
public:
using SeedT = typename RandomEngineT::result_type;
protected:
SeedT seed_ = SeedT::default_seed;
RandomEngineT reng_;
public:
SamplingFilter (bool extract_removed_indices = false)
: FilterIndices<PointT> (extract_removed_indices)
{}
void setSeed (SeedT seed) { seed_ = seed; }
SeedT getSeed () const { return seed_; }
protected:
virtual bool initCompute () override
{
reng_.seed (seed_);
return PCLBase<PointT>::initCompute ();
}
}
} |
That's a must.
Could you please expand on this? Does it make sense to create a hierarchy? Do you envision other If so, it might make sense to create a Mixin or CRTP since technically, this class brings in an independent and optional capability which can be mixed and matched with other independent capabilities. (Though both would be a relatively new design pattern for PCL). Some detailed description can be found here PS: I'm overall not fond of classes for filters since it makes it hard to create new with low boiler plate and apply in a row beautifully. Just reporting my bias against full fledged classes for something that might not need classes. |
Check the ctor and seed method invoked with the 3rd and 2nd signature respectively. It's an "issue" of completeness, possibly with not much use in our domain.
Yes. All derived classes from FilterIndices with some random capabilities. If you open the inheritance diagram, you'll see a bunch of types with very suggestive names.
This is indeed the question... This is a functionality which is applicable to a lot of other non-filter based classes. The only limitation is that it needs a mechanism which to ensures that it is launched before any "true processing" takes place. While I find CRTP amusing, I don't believe it has room for the current API as it is. The way to go here, might be actually through multiple inheritance. This class is as an independent base class, so diamond inheritance would not be an issue per se. |
I should have worded it like: "Do you envision classes with essentially the same functionality being used with and without
Templated inheritance only comes into question if the previous question's answer is yes.
Maybe, if it's not a particularly problematic (shouldn't be). Else it's better to leave it and till someone requests it. |
If we follow the idea of creating a base class with seed management functionality, then why limit it to filters? There are numerous algorithms in other modules that require random numbers. So taking this to the extreme, |
Not having to create the functions, manage the generator and that's about it. Mixin are supposed to be simple classes (like Boost adding in arithmetic and comparison operations via templates) with a small but used often functionality |
It's refactoring thing. It will allow us to unify the way we handle seed and engine management in all classes that need it, and hopefully, reduce some code duplication. This being said. I was mentally prepping up to create a base class just for random capabilities and resort to multiple inheritance. Notice how this is already touching two mantras! You guys have been mentioning composition instead on inheritance and at this point I feel I need to ask you to sketch me a proof of concept so that I can better what your optimal strategies to address this are. I see a case for composition when there are multiple functionality sets that you might want to enable/ disable based on the class, but for our particular case, I'm finding it hard to grasp the benefits. I'm hoping that with your PoC that will be made clear. |
Orthogonal inheritance feels better than a chain of inheritance. CRTP might help prevent users from making mistakes such as a pointer to the random-capable base class. |
The first example goes along the lines of what I was suggesting but it is extended with more capabilities (FirstN).
I'm not sure I fully get this comment, because AFAIK you can still extract a pointer to any of the base classes of a CRTP object. Can you post a snippet illustrating this mistake that the CRTP approach prevents? |
It's just two functions, come on :) And you still need to call mixin constructor explicitly to propagate the seed. Generator management can be done in a helper object and "composed in" into the class. But yeah, I'm not against mixins actually, just wanted to hear some good arguments. |
If we use a simple multiple inheritance, it allows If we use CRTP, the base class becomes
That's correct, but I'm assuming we'll might see similar refactoring occurring once we get more eyes on more parts of the project (registration looks tempting...). Getting some discussion on a toy example might help to set a direction for later.
Yeah, that's the complete composition approach. This fits in well when there's not any function implemented for a class (eg: this case, the seed is merely read and written). I was providing the other approaches assuming this was the baseline to compare to. For completeness sake, I'll reproduce a sample of code below: struct FirstN { std::size_t sample_size; };
struct RandomFilter2 {
RandomFilter2(std::size_t N): first_n_(N) {}
auto& getSamplingSize() { return first_n_.sample_size; }
auto getSamplingSize() const { return first_n_.sample_size; }
protected:
FirstN first_n_;
};
Not a lot. Type-traits + free-standing functions are better for complicated cases since C++ lacks traits. But the implementation also gets complicated. Mixin and CRTP fill the niche of non-trivial, but not complicated. A sample impl using type traits and free-standing functions is the template <class T>
struct has_begin_end; // this is obv not that trivial, needs public members or template specialization
template <class T>
using IsClassicalIterator = std::enable_if_t<has_begin_end<T>::value, bool>;
struct Container; // normal implementation, use composition or inheritance or whatever
template<typename T, IsClassicalIterator<T> = true>
auto begin(const T& c) { return c.begin(); } |
This is true, but I don't buy this as an argument in favor of CRTP. People might do a lot of crazy things in C++ and it's not our job to save them. Granted,
Well, agree. So from my side:
|
Agreed with all 👍 |
Marking this as stale due to 30 days of inactivity. It will be closed in 7 days if no further activity occurs. |
Having a seed is something which is common to all sampling classes. I have a rough feeling it would be good to create a SamplingFilter base class. Something for another PR.
Originally posted by @SergioRAgostinho in https://github.com/_render_node/MDE3OlB1bGxSZXF1ZXN0UmV2aWV3MzcwOTgwNjYy/pull_request_reviews/more_threads
This class should use modern C++11/14
<random>
header along with modern PRNG and entropy sources provided by stdlibThe text was updated successfully, but these errors were encountered: