Library: improve helper to deal with self-shadowing ctor (see: #963)

Whenever a class defines a single-arg templated constructor,
there is danger to shadow the auto-generated copy operations,
leading to insidious failures.

Some months ago, I did the ''obvious'' and added a tiny helper,
allowing to mask out the dangerous case when the ''single argument''
is actually the class itself (meaning, it is a copy invocation and
not meant to go through this templated ctor...


As this already turned out as tremendously helpful, I now extended
this helper to also cover cases where the problematic constructor
accepts variadic arguments, which is quite common with builder-helpers
This commit is contained in:
Fischlurch 2024-04-01 19:40:19 +02:00
parent fc084c1ca5
commit be4d809a23
4 changed files with 24 additions and 5 deletions

View file

@ -136,9 +136,28 @@ namespace meta {
namespace {
template<typename...>
struct _ExtractFirst
{
using Type = void;
};
template<typename X, typename...XS>
struct _ExtractFirst<X,XS...>
{
using Type = X;
};
}
/** helper to extract the first argument from a variadic arg pack, if any */
template<typename...XS>
using extractFirst_t = typename _ExtractFirst<XS...>::Type;
/** helper to prevent a template constructor from shadowing inherited copy ctors */
template<typename ARG, class SELF>
using disable_if_self = disable_if<std::is_same<std::remove_reference_t<ARG>, SELF>>;
template<class SELF, typename ...ARGS>
using disable_if_self = disable_if<std::is_same<std::remove_cv_t<std::remove_reference_t<extractFirst_t<ARGS...>>>
, SELF>>;

View file

@ -282,7 +282,7 @@ namespace lib {
* - `void(RandomDraw&, ...)` : the function manipulates the current
* instance, to control parameters dynamically, based on input.
*/
template<class FUN, typename =disable_if_self<FUN, RandomDraw>>
template<class FUN, typename =disable_if_self<RandomDraw, FUN>>
RandomDraw(FUN&& fun)
: Lazy{Disabled()}
, probability_{1.0}

View file

@ -164,7 +164,7 @@ namespace gear {
* this reference is dangling and using it further will
* lead to SEGFAULT or memory corruption.
*/
template<class FUN, typename =disable_if_self<FUN, SpecialJobFun>>
template<class FUN, typename =disable_if_self<SpecialJobFun, FUN>>
explicit
SpecialJobFun (FUN&& someFun)
: _Handle{selfAttached (new SpecialExecutor(forward<FUN> (someFun)))}

View file

@ -357,7 +357,7 @@ namespace test{
installInitialiser(fun, buildInit([](int){ return 0; }));
}
// prevent this ctor from shadowing the copy ctors //////TICKET #963
template<typename FUN, typename =disable_if_self<FUN, LazyDemo>>
template<typename FUN, typename =disable_if_self<LazyDemo, FUN>>
LazyDemo (FUN&& someFun)
: LazyInit{MarkDisabled()}
, fun{}