Проверьте, является ли шаблон удаленной по умолчанию функции явно специализированным для определенного типа c? - PullRequest
1 голос
/ 03 апреля 2020

(Этот вопрос был значительно отредактирован, извините.)

Предположим, у меня есть несколько шаблонов функций non-constexpr, которые по умолчанию удаляются:

template <typename T> void foo() = delete;
template <typename T> int  bar(int x) = delete;
// etc.

и имеют определенную специализацию как исключение из общего случая удаления.

Я хочу написать код (например, класс черты?), который, учитывая идентификатор одной из этих функций и типа T, обнаруживает во время компиляции, является ли указанная функция явно специализированной для типа T. Код должен быть обобщенным c, т.е. не должен быть отдельным детектором для каждой из функций.

Примечания:

  • Looking для решения C ++ 11.
  • Мы можем предположить, что указанная функция удалена по умолчанию - если это помогает.
  • В идеале, она должна выглядеть так: instantiation_exists<decltype(foo), foo, int>::value или instantiation_exists<int>(foo, tag<int>) или instantiation_exists(foo, tag<int>) или что-то в этом духе.

Редактировать: @ Jarod42's написал SFINAE пример в комментарии к более ранней версии этого вопрос, который был о человеке детектор Я попытался обобщить / обобщить его, используя параметр шаблона-шаблона:

#include <type_traits>

template <typename T> void foo() = delete;
template <> void foo<int>() {}

template <template<typename U> typename F, typename T, typename = decltype(F<T>()) >
std::true_type test(int);

template  <template<typename U> typename F, typename T>
std::false_type test(...);

template <typename T>
using foo_is_defined = decltype(test<foo<T>, T>(0));

static_assert(foo_is_defined<int>::value);
static_assert(not foo_is_defined<int*>::value);

, но это было ау sh (Coliru).

1 Ответ

1 голос
/ 03 апреля 2020

Мы не можем передать функцию шаблона или перегрузки в параметре шаблона.

Мы можем превратить эти функции в функтор:

template <typename T>
struct identity_type
{
    using type = T;  
};

template <typename F, typename T, typename = decltype(std::declval<F>()(identity_type<T>{})) >
std::true_type test(int);

template  <typename F, typename T>
std::false_type test(...);

auto foos = [](auto tag, auto&&... args)
-> decltype(foo<typename decltype(tag)::type>((decltype(args))(args)...))
{
    return foo<typename decltype(tag)::type>((decltype(args))(args)...);
};

template <typename T>
using is_foo = decltype(test<decltype(foos), T>(0));

Демо

Я использую generi c лямбда, поэтому C ++ 14.

в C ++ 11, это было бы действительно многословно:

struct foos
{
    template <typename T, typename... Ts>
    auto operator()(identity_type<T>, Ts&&... args) const
    -> decltype(foo<T>(std::forward<Ts>(args)...))
    {
        return foo<T>(std::forward<Ts>(args)...);
    };
};
...