Home > Blockchain >  Cannot infer template argument 'T' when a second parameter includes 'T'
Cannot infer template argument 'T' when a second parameter includes 'T'

Time:07-23

Given this template function:

template <
    typename T,
    typename U,
    typename = std::enable_if<
        std::is_same_v<U, std::unique_ptr<T>> ||
        std::is_same_v<U, std::shared_ptr<T>>>>
T foo(U val) {
  if constexpr (std::is_same_v<U, std::unique_ptr<T>>) {
    return *val;
  }
  return *val;
}

I want to call it like this:

int x = foo(std::make_unique<int>(1));

But, it's giving this error:

Candidate template ignored: couldn't infer template argument 'T'

I can fix it by providing the type T explicitly:

int x = foo<int>(std::make_unique<int>(1));

Is it possible to fix it such that it can infer? The type is clearly embedded in the typename U but it does not seem to "propagate" to T.

CodePudding user response:

SFINAE constraints don't affect template argument deduction. Your compiler has to deduce T and U first, without even looking at your enable_if_t<...>.

I'd do something like this:

#include <memory>
#include <type_traits>

namespace impl
{
    template <typename A, template <typename...> typename B>
    struct specialization_of : std::false_type {};

    template <template <typename...> typename T, typename ...P>
    struct specialization_of<T<P...>, T> : std::true_type {};
}

template <typename A, template <typename...> typename B>
concept specialization_of = impl::specialization_of<A, B>::value;


template <typename T>
requires specialization_of<T, std::unique_ptr> || specialization_of<T, std::shared_ptr>
auto foo(T val)
{
    if constexpr (specialization_of<T, std::unique_ptr>)
    {
        return *val;
    }
    return *val;
}

[I also want] std::is_same_v<U, std::function<T()>>

Then you need a specialized template just for this task. Something like:

template <typename T, typename U>
struct foo : std::false_type {};
template <typename T, typename U>
struct foo<std::function<T()>, U> : std::is_same<T, U> {};

Then foo<std::function<int()>, int> is true.

  •  Tags:  
  • c
  • Related