目标是拥有一个接受任意数量数组的函数<双,N>任意大小为N(但这对所有人来说都可以是相同的(,并且在函数体内部具有可用的N。例如,假设我想使用N返回另一个用户定义的数组类型,MyArray<N>。我希望它更清楚!谢谢,我是变种模板的新手,不知道如何做到这一点。感谢任何帮助或提示。谢谢
#include <array>
using namespace std;
template<int N>
struct MyArray {};
// here I don't know how to deduce N and keep the variadic number of parameters
template<int N, typename... Ts>
MyArray<N> foo(const Ts&... ts)
{
// somehow use the variadic parameters
MyArray<N> a;
return a;
}
int main()
{
array<double, 3> a, b, c;
auto d = foo(a, b, c);
}
我不完全确定我是否理解您的函数要做什么;求和所有阵列并将N加到每个字段";,如果不是,我的例子无论如何都应该是一个很好的例子。
template<size_t N, typename... Ts>
std::array<double, N> foo(std::array<double, N> first)
{
for (size_t i = 0; i < N; ++i) {
first[i] += N;
}
return first;
}
template<size_t N, typename... Ts>
std::array<double, N> foo(const std::array<double, N>& first, Ts&... ts)
{
std::array<double, N> result = foo(ts...);
for (size_t i = 0; i < N; ++i) {
result[i] += first[i];
}
return result;
}
template<size_t N>
void print_array(const std::array<double, N>& arr) {
for (double x : arr) {
std::cout<<x<<" ";
}
std::cout<<"n";
}
int main() {
std::array<double, 3> a = {1, 2, 3};
std::array<double, 3> b = {4, 5, 6};
std::array<double, 3> c = {7, 8, 9};
auto d = foo(a, b, c);
print_array(d);
d = foo(a, b);
print_array(d);
}
我想您可以接受std::array
的序列,推导维度,并且SFINAE只有在维度重合时才启用该函数。
我的意思是。。。
template <std::size_t N0, std::size_t ... Ns,
std::enable_if_t<((N0 == Ns) && ...), int> = 0>
auto foo (std::array<double, N0> const & a0,
std::array<double, Ns> const & ... as)
{
std::array<double, N0> d;
d[0] = (a0[0] + ... + as[0]);
d[0] += N0;
return d;
}
或者
template <std::size_t ... Ns, std::size_t N = (Ns + ...)/sizeof...(Ns),
std::enable_if_t<((N == Ns) && ...), int> = 0>
auto foo (std::array<double, Ns> const & ... as)
{
std::array<double, N> d;
d[0] = (N + ... + as[0]);
return d;
}
或者,如果你喜欢的话,推导出第一个大小并强加以下类型是相同的
template <std::size_t N0, typename ... Ts,
std::enable_if_t<((std::is_same_v<std::array<double, N0>, Ts>) && ...), int> = 0>
auto foo (std::array<double, N0> const & a0, Ts const & ... as)
{
std::array<double, N0> d;
d[0] = (a0[0] + ... + as[0]);
d[0] += N0;
return d;
}
正如François Andrieux所指出的,相反,SFINAE方式可以遵循static_assert()
方式,以获得更有意义的消息错误
template <std::size_t N0, std::size_t ... Ns>
auto foo (std::array<double, N0> const & a0,
std::array<double, Ns> const & ... as)
{
static_assert( ((N0 == Ns) && ...), "some clear error message!");
// ...
但是,通过这种方式,您无法开发foo()
的不同版本和替代版本。
看看什么解决方案对你更有用。
我终于做到了,仍然不好的元素是Foo模板部分中N的类型必须与std::array中使用的类型完全匹配,以指示大小,这使得N在内部是已知的,并且可以用来创建MyArray对象。
基本上,我必须将参数包声明为模板(因此具有一个带有模板包的模板(。Ts…之所以存在,是因为数组通常需要2个以上的模板参数。
#include <array>
using namespace std;
template<int N>
struct MyArray {};
template<typename T, long unsigned N, typename... Ts, template<typename, long unsigned, typename...> typename... Arrays>
MyArray<N> Foo(const Arrays<T, N, Ts...>&... arrays)
{
return MyArray<N>{};
}
int main()
{
array<double, 3> a, b, c;
MyArray<3> d = Foo(a, b, c);
auto e = Foo(a, b);
return 0;
}