根据模板参数固定数量的模板函数参数
Fixed number of template function arguments according to template argument
我目前正在寻找一种解决方案,以提供模板化 类' 构造函数并根据参数数量 N
来运行固定模板。我的模板是 template<typename T, unsigned int N>
的形式。这个想法是以下将起作用:
MyClass<int, 4> object(1, 2, 3, 4);
虽然以下应该会失败(依此类推):
MyClass<int, 4> object(1, 2, 3);
MyClass<int, 4> object(1, 2, 3, 4, 5);
我正在考虑类似 MyClass(T arg1, ..., T argN){...}
但自动生成的内容。我只找到了有关如何为模板提供一个或多个参数的解决方案。但没有固定计数。
我希望有人能帮助我。提前谢谢您!
您可以使用中间类型并使用 std::index_sequence
:
template <typename T, std::size_t>
using always_t = T;
template <typename T, typename Seq> struct MyClassImpl;
template <typename T, std::size_t ... Is>
struct MyClassImpl<T, std::index_sequence<Is...>>
{
MyClassImpl(always_t<T, Is>...);
};
template <typename T, std::size_t N>
using MyClass = MyClassImpl<T, std::make_index_sequence<N>>;
Demo.
或者,类似地,使用更简单的 MyClassImpl
,复杂性在别名中移动:
template <typename ...Ts>
struct MyClassImpl
{
MyClassImpl(Ts... args);
};
template <typename T, std::size_t>
using always_t = T;
template <typename T, typename Seq>
struct MyClassAlias;
template <typename T, std::size_t... Is>
struct MyClassAlias<T, std::index_sequence<Is...>>
{
using type = MyClassImpl<always_t<T, Is>...>;
};
template <typename T, std::size_t N>
using MyClass = typename MyClassAlias<T, std::make_index_sequence<N>>::type;
可以给重载加上约束,比如
template <typename T, std::size_t N>
struct MyClass {
// pre-C++20
template <typename... Args, std::enable_if_t<sizeof...(Args) == N, int> = 0>
MyClass(Args&&... args) { /* ... */ }
// or alternatively, post-C++20,
template <typename... Args>
requires (sizeof...(Args) == N)
MyClass(Args&&... args) { /* ... */ }
};
请注意,在 N == 1
的情况下,在某些情况下,这些模板将优先于自动生成的复制构造函数。如果这是一个潜在问题,那么您将需要进一步限制模板以防止出现这种情况。 Here is an example of how you might do so.
如果您不需要使用 SFINAE 来区分其他构造函数,您也可以使用 static_assert
:
template <typename... Args>
MyClass(Args&&... args) {
static_assert(sizeof...(Args) == N);
// ...
}
我目前正在寻找一种解决方案,以提供模板化 类' 构造函数并根据参数数量 N
来运行固定模板。我的模板是 template<typename T, unsigned int N>
的形式。这个想法是以下将起作用:
MyClass<int, 4> object(1, 2, 3, 4);
虽然以下应该会失败(依此类推):
MyClass<int, 4> object(1, 2, 3);
MyClass<int, 4> object(1, 2, 3, 4, 5);
我正在考虑类似 MyClass(T arg1, ..., T argN){...}
但自动生成的内容。我只找到了有关如何为模板提供一个或多个参数的解决方案。但没有固定计数。
我希望有人能帮助我。提前谢谢您!
您可以使用中间类型并使用 std::index_sequence
:
template <typename T, std::size_t>
using always_t = T;
template <typename T, typename Seq> struct MyClassImpl;
template <typename T, std::size_t ... Is>
struct MyClassImpl<T, std::index_sequence<Is...>>
{
MyClassImpl(always_t<T, Is>...);
};
template <typename T, std::size_t N>
using MyClass = MyClassImpl<T, std::make_index_sequence<N>>;
Demo.
或者,类似地,使用更简单的 MyClassImpl
,复杂性在别名中移动:
template <typename ...Ts>
struct MyClassImpl
{
MyClassImpl(Ts... args);
};
template <typename T, std::size_t>
using always_t = T;
template <typename T, typename Seq>
struct MyClassAlias;
template <typename T, std::size_t... Is>
struct MyClassAlias<T, std::index_sequence<Is...>>
{
using type = MyClassImpl<always_t<T, Is>...>;
};
template <typename T, std::size_t N>
using MyClass = typename MyClassAlias<T, std::make_index_sequence<N>>::type;
可以给重载加上约束,比如
template <typename T, std::size_t N>
struct MyClass {
// pre-C++20
template <typename... Args, std::enable_if_t<sizeof...(Args) == N, int> = 0>
MyClass(Args&&... args) { /* ... */ }
// or alternatively, post-C++20,
template <typename... Args>
requires (sizeof...(Args) == N)
MyClass(Args&&... args) { /* ... */ }
};
请注意,在 N == 1
的情况下,在某些情况下,这些模板将优先于自动生成的复制构造函数。如果这是一个潜在问题,那么您将需要进一步限制模板以防止出现这种情况。 Here is an example of how you might do so.
如果您不需要使用 SFINAE 来区分其他构造函数,您也可以使用 static_assert
:
template <typename... Args>
MyClass(Args&&... args) {
static_assert(sizeof...(Args) == N);
// ...
}