c++ - 确定最佳转换的 Variadic 模板

标签 c++ type-conversion variadic-templates c++14 overload-resolution

我们如何实现一个可变参数模板,给定类型 T 和类型列表 E1E2, ... EN,确定从 T 转换的列表的类型> 根据重载决议,那种类型是最好的?

如果不存在最佳转换,则

void 应该是输出 - 换句话说,当存在歧义或 T 无法转换为列表中的任何类型时。
请注意,这意味着我们的模板应该是 SFINAE 友好的,即当不存在最佳转换时不会出现硬错误。

以下 static_assert 应该成功:

static_assert( std::is_same< best<int, long, short>,       void >{}, "" );
static_assert( std::is_same< best<int, long, std::string>, long >{}, "" );
static_assert( std::is_same< best<int>,                    void >{}, "" );

(为简单起见,假设 best 是引用实际模板的别名模板)

此案例未指定:

static_assert( std::is_same< best<int, int, int>, ???>{}, "" );

此处可以接受voidint。 (如果选择后者,那么我们仍然可以在包装器模板中检查结果类型是否在列表中包含两次,如果是,则输出 void)。

最佳答案

我目前最好的方法:

#include <type_traits>

template <class T> using eval = typename T::type;

template <class T> struct identity {using type = T;};

template <typename T, typename... E>
class best_conversion
{
    template <typename...> struct overloads {};

    template <typename U, typename... Rest>
    struct overloads<U, Rest...> :
        overloads<Rest...>
    {
        using overloads<Rest...>::call;

        static identity<U> call(U);
    };

    template <typename U>
    struct overloads<U>
    {
        static identity<U> call(U);
    };

    template <typename... E_>
    static identity<eval<decltype(overloads<E_...>::call(std::declval<T>()))>>
    best_conv(int);

    template <typename...>
    static identity<void> best_conv(...);

public:

    using type = eval<decltype(best_conv<E...>(0))>;
};

template <typename... T>
using best_conversion_t = eval<best_conversion<T...>>;

Demo .对于上面的“未指定”情况,此模板将为您提供 int .

基本思想是将一堆带有一个参数的重载函数放入名称查找将查找的不同范围内,每个重载的参数和返回类型对应于我们列表中的一种类型。
overloads通过递归地引入一个声明 call 来完成这项工作一次调整所有以前介绍的call来自基础特化的 using声明。那样都call s 在不同的范围内,但在涉及重载决议时被同等考虑。

然后在函数模板中应用 SFINAE best_conv检查是否调用了call (在 overloads 内)格式正确:如果是,则采用所选声明的返回类型(根据定义,参数类型)并将其用作我们的结果 - 这将是我们正在寻找的类型。< br/> 还提供了 best_conv 的第二个重载返回 void并且可以选择为默认值(当 SFINAE 在第一个重载中应用并将其踢出候选集时)。

返回类型使用identity<>在使用例如时避免类型衰减数组或函数指针类型。

关于c++ - 确定最佳转换的 Variadic 模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27338428/

相关文章:

python - MATLAB 到 Python 转换 : vectors, 数组,索引元素

c++ - 可变参数模板中递归模板函数的终止问题

C++:使用类型作为映射键引入模板替换错误

c++ - 复制到较小类型的数据结构时出现数据丢失警告

c++ - 为什么模板没有重新定义,为什么都写在头文件里了?

c++ - 英特尔集成显卡错误识别 (DXGI)

c - 将字符串数组转换为 C 中的字符串

.net - 转换与 CType

c++ - 包扩展不在最后一个参数中的可变参数函数模板

c++ - 是否有 tbb::parallel_for 的中断命令