SFINAE根据类值模板参数选择构造函数

问题描述 投票:0回答:2

我正在尝试编写一个类,该类根据类自己的模板参数的值公开不同的构造函数。试图做到这一点的天真的代码如下:

// C++14
#include <type_traits>

template <int compile_time_w = -1, int compile_time_h = -1>
struct Grid
{
    template <std::enable_if_t<compile_time_w < 0 && compile_time_h < 0, int> = 0>
    Grid(int runtime_w, int runtime_h) : _w(runtime_w), _h(runtime_h) {}

    template <std::enable_if_t<compile_time_w < 0 && compile_time_h >= 0, int> = 0>
    Grid(int runtime_w) : _w(runtime_w), _h(compile_time_h) {}

    template <std::enable_if_t<compile_time_w >= 0 && compile_time_h < 0, int> = 0>
    Grid(int runtime_h) : _w(compile_time_w), _h(runtime_h) {}

    template <std::enable_if_t<compile_time_w >= 0 && compile_time_h >= 0, int> = 0>
    Grid() : _w(compile_time_w), _h(compile_time_h) {}

    int _w, _h;
};

int main()
{
    // Grid<2, 2> grid; // any combination of template parameters + constructor parameters fails to compile

    return 0;
}

编译类而不进行任何实例化都可以,但是尝试以任何方式实例化它或容量总是失败。编译错误始终具有相同的格式,并且会向SFINAE应触发的每个构造函数报告该错误:

error: no type named ‘type’ in ‘struct std::enable_if’

显然std::enable_if可以按预期工作,但是某种程度上不应视为错误。关于这一切的任何线索吗?

c++ templates sfinae
2个回答
1
投票

为了使用SFINAE,模板参数必须是当前模板的一部分。由于compile_time_wcompile_time_h是类模板参数的一部分,因此它们不可用。要修复它,请将它们添加到每个功能模板中,例如

template <int compile_time_w = -1, int compile_time_h = -1>
struct Grid
{
    template <int compile_time_w_l = compile_time_w, int compile_time_h_l = compile_time_h, std::enable_if_t<compile_time_w_l < 0 && compile_time_w_l < 0, int> = 0>
    Grid(int runtime_w, int runtime_h) : _w(runtime_w), _h(runtime_h) {}

    template <int compile_time_w_l = compile_time_w, int compile_time_h_l = compile_time_h, std::enable_if_t<compile_time_w_l < 0 && compile_time_w_l >= 0, int> = 0>
    Grid(int runtime_w) : _w(runtime_w), _h(compile_time_h) {}

    template <int compile_time_w_l = compile_time_w, int compile_time_h_l = compile_time_h, std::enable_if_t<compile_time_w_l >= 0 && compile_time_w_l < 0, int> = 0>
    Grid(int runtime_h) : _w(compile_time_w), _h(runtime_h) {}

    template <int compile_time_w_l = compile_time_w, int compile_time_h_l = compile_time_h, std::enable_if_t<compile_time_w_l >= 0 && compile_time_w_l >= 0, int> = 0>
    Grid() : _w(compile_time_w), _h(compile_time_h) {}

    int _w, _h;
};

int main()
{
    Grid<2, 2> grid; // any combination of template parameters + constructor parameters fails to compile

    return 0;
}

0
投票

SFINAE使用功能模板的模板参数;您应该使构造函数模板拥有自己的模板参数,并使用std::enable_if而不是类模板参数进行检查;否则,通过某些类模板实例化,所有构造函数模板都将被实例化并导致错误。

template <int w = compile_time_w, int h = compile_time_h, std::enable_if_t<w < 0 && h < 0, int> = 0>
Grid(int runtime_w, int runtime_h) : _w(runtime_w), _h(runtime_h) {}

template <int w = compile_time_w, int h = compile_time_h, std::enable_if_t<w < 0 && h >= 0, int> = 0>
Grid(int runtime_w) : _w(runtime_w), _h(compile_time_h) {}

template <int w = compile_time_w, int h = compile_time_h, std::enable_if_t<w >= 0 && h < 0, int> = 0>
Grid(int runtime_h) : _w(compile_time_w), _h(runtime_h) {}

template <int w = compile_time_w, int h = compile_time_h, std::enable_if_t<w >= 0 && h >= 0, int> = 0>
Grid() : _w(compile_time_w), _h(compile_time_h) {}

LIVE

© www.soinside.com 2019 - 2024. All rights reserved.