SFINAE 到 select 构造函数基于 class 值模板参数
SFINAE to select constructor based on class value template parameter
我正在尝试编写一个 class,它根据 class 自己的模板参数的值公开不同的构造函数。尝试执行此操作时想到的天真代码如下:
// 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;
}
在不对其进行任何实例化的情况下编译 class 工作正常,但尝试以任何方式或容量对其进行实例化总是失败。编译错误始终具有相同的格式,并在 SFINAE 应触发的每个构造函数中报告:
error: no type named ‘type’ in ‘struct std::enable_if’
显然 std::enable_if
正在按预期工作,但不知何故不应将其视为错误。关于这一切的任何线索?
SFINAE 作用于函数模板的模板参数;您应该使构造函数模板拥有自己的模板参数,并使用 std::enable_if
而不是 class 模板参数检查它们;否则,对于某些 class 模板实例化,所有构造函数模板都将被实例化并导致错误。
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) {}
为了使用 SFINAE,模板参数必须是当前模板的一部分。由于 compile_time_w
和 compile_time_h
是 class 模板参数的一部分,因此它们不可用。要修复它,请将它们添加到每个函数模板中,例如
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;
}
以及C++20版本:
template <int compile_time_w = -1, int compile_time_h = -1>
struct Grid
{
Grid(int runtime_w, int runtime_h) requires (compile_time_w < 0 && compile_time_h < 0)
: _w(runtime_w), _h(runtime_h) {}
Grid(int runtime_w) requires(compile_time_w < 0 && compile_time_h >= 0)
: _w(runtime_w), _h(compile_time_h) {}
Grid(int runtime_h) requires(compile_time_w >= 0 && compile_time_h < 0)
: _w(compile_time_w), _h(runtime_h) {}
Grid() requires(compile_time_w >= 0 && compile_time_h >= 0)
: _w(compile_time_w), _h(compile_time_h) {}
int _w, _h;
};
我正在尝试编写一个 class,它根据 class 自己的模板参数的值公开不同的构造函数。尝试执行此操作时想到的天真代码如下:
// 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;
}
在不对其进行任何实例化的情况下编译 class 工作正常,但尝试以任何方式或容量对其进行实例化总是失败。编译错误始终具有相同的格式,并在 SFINAE 应触发的每个构造函数中报告:
error: no type named ‘type’ in ‘struct std::enable_if’
显然 std::enable_if
正在按预期工作,但不知何故不应将其视为错误。关于这一切的任何线索?
SFINAE 作用于函数模板的模板参数;您应该使构造函数模板拥有自己的模板参数,并使用 std::enable_if
而不是 class 模板参数检查它们;否则,对于某些 class 模板实例化,所有构造函数模板都将被实例化并导致错误。
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) {}
为了使用 SFINAE,模板参数必须是当前模板的一部分。由于 compile_time_w
和 compile_time_h
是 class 模板参数的一部分,因此它们不可用。要修复它,请将它们添加到每个函数模板中,例如
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;
}
以及C++20版本:
template <int compile_time_w = -1, int compile_time_h = -1>
struct Grid
{
Grid(int runtime_w, int runtime_h) requires (compile_time_w < 0 && compile_time_h < 0)
: _w(runtime_w), _h(runtime_h) {}
Grid(int runtime_w) requires(compile_time_w < 0 && compile_time_h >= 0)
: _w(runtime_w), _h(compile_time_h) {}
Grid(int runtime_h) requires(compile_time_w >= 0 && compile_time_h < 0)
: _w(compile_time_w), _h(runtime_h) {}
Grid() requires(compile_time_w >= 0 && compile_time_h >= 0)
: _w(compile_time_w), _h(compile_time_h) {}
int _w, _h;
};