Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive enable_if and type transform

I'd like to add same number pointers from typename U to typename T, for example when T = int*** and U = int*, the result is int****. So, I write the following:

#include <type_traits>

template <typename T, typename U,
          typename std::enable_if_t<std::is_pointer<U>::value>* = nullptr>
auto addPointer(T, U)
    -> decltype(addPointer(std::declval<std::add_pointer_t<T>>(),
                           std::declval<std::remove_pointer_t<U>>()));

template <typename T, typename U,
          typename std::enable_if_t<!std::is_pointer<U>::value>* = nullptr>
auto addPointer(T, U) -> T;

int main()
{
    using t =
        decltype(addPointer(std::declval<int***>(), std::declval<int*>()));
}

and I get the following on Linux clang 3.7:

$ clang++ -std=c++14 -stdlib=libc++ -lc++abi -Wall -Wextra a.cpp 
a.cpp:16:18: error: no matching function for call to 'addPointer'
        decltype(addPointer(std::declval<int***>(), std::declval<int*>()));
                 ^~~~~~~~~~
a.cpp:5:6: note: candidate template ignored: substitution failure [with T = int ***, U =
      int *, $2 = nullptr]: call to function 'addPointer' that is neither visible in the
      template definition nor found by argument-dependent lookup
auto addPointer(T, U)
     ^
/usr/bin/../include/c++/v1/type_traits:244:78: note: candidate template ignored: disabled
      by 'enable_if' [with T = int ***, U = int *]
  ...<bool _Bp, class _Tp = void> using enable_if_t = typename enable_if<_Bp, _Tp>::type;
                                                                         ^
1 error generated.

Why do I get the error?

like image 893
user3717819 Avatar asked Nov 26 '25 06:11

user3717819


1 Answers

As we're dealing with scalars, ADL will not look in the global namespace. Not only can the fallback overload not be found this way, the overload you're currently defining cannot be referred to in the trailing-return-type.

With C++14, there is a nicer solution to your problem, which circumvents that issue:

template <typename T>
T addPointer(T, ...);

template <typename T, typename U>
auto addPointer(T t, U* u) {return addPointer(&t, *u);}

Demo.

like image 160
Columbo Avatar answered Nov 28 '25 20:11

Columbo