首页 > 解决方案 > 检查默认删除的函数模板是否明确专门用于特定类型?

问题描述

(这个问题已经过大量编辑,抱歉。)

假设我有几个非常量函数模板,默认被删除:

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

并且有一些明确的特化作为一般情况删除的例外。

我想编写代码(例如特征类?),给定这些函数之一的标识符和类型 T,在编译时检测指定的函数是否明确专门用于类型 T。代码需要通用的,即不是每个功能的单独检测器。

笔记:


编辑: @Jarod42 在对这个问题的早期版本的评论中写了一个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);

但那是一种洗涤(Coliru)。

标签: c++c++11template-meta-programmingtemplate-instantiationdelete-keyword

解决方案


我们不能传递模板函数,或者模板参数中的重载。

我们可以在仿函数中转换这些函数:

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));

演示

我使用通用 lambda,所以 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)...);
    };
};

推荐阅读