我有以下问题:
template< typename T, size_t N, size_t... N_i >
class A
{
public:
// ...
// first implementation
template< size_t M = sizeof...(N_i)+1, typename std::enable_if< M!=1, size_t >::type = 0 >
A<T, N_i...> operator[]( size_t i )
{
A< T, N_i... > res{ ... };
return res;
}
// second implementation
template< size_t M = sizeof...(N_i)+1, typename std::enable_if< M==1, size_t >::type = 0 >
T operator[]( size_t i )
{
return ... ;
}
};
正如您在上面所看到的,我尝试实现一个类A
,它希望模板参数为T
类型(例如int
或float
)和{{1很多sizeof...(N_i)+1
。
取决于传递的size_t
(即size_t
)的数量,我将对成员函数sizeof...(N_i)+1
使用不同的实现,结果类型不同:
operator[](size_t)
的一个实现,返回类型为sizeof...(N_i)+1 > 1
(在代码中称为“第一个实现”)A < T, N_i... >
,返回类型为sizeof...(N_i)+1 == 1
(在代码中称为“第二个实现”)。 不幸的是,我不知道如何实现这一点 - 上面的解决方案不起作用。有人有想法吗?
非常感谢提前。
答案 0 :(得分:2)
如果修改
A< T, N_i... > res{ ... };
在
A< T, N_i... > res{ };
和
return ... ;
在
return T{} ;
还不够?
---编辑---
否:正如Jarod42指出的那样(谢谢!),还不够。
所以我提出了以下解决方案,基于类模板特化和std::conditional
以避免使用SFINAE
#include <iostream>
#include <type_traits>
template< typename, size_t...>
class A;
template< typename T, size_t N, size_t... N_i >
class A<T, N, N_i...>
{
public:
template <typename Next = typename std::conditional<sizeof...(N_i),
A<T, N_i...>, T>::type>
Next operator[] (size_t i)
{ return Next{}; }
};
int main(int argc, char* argv[])
{
A<int, 2, 4> a;
std::cout << a[1][2] << std::endl;
return 0;
}
如果您不想使用specialize A
,则可以添加A
的子结构来执行脏工作。
#include <iostream>
#include <type_traits>
template< typename T, size_t N, size_t... N_i >
class A
{
template <typename U, size_t ... O_i>
struct Next
{ using type = A<U, O_i...>; };
template <typename U>
struct Next<U>
{ using type = U; };
public:
using next_t = typename Next<T, N_i...>::type;
next_t operator[] (size_t i)
{ return next_t{}; }
};
int main(int argc, char* argv[])
{
A<int, 2, 4> a;
std::cout << a[1][2] << std::endl;
return 0;
}
答案 1 :(得分:2)
A<T, N_i...>
对空N_i
无效。
作为解决方法,您可以使用间接:
template <typename, std::size_t ...>
struct PopFrontA
{
using type = void; // Dummy type for A<T, N>
};
template< typename T, std::size_t N, std::size_t... N_i > class A;
template <typename T, std::size_t N, std::size_t N2, std::size_t ... Ns>
struct PopFrontA<T, N, N2, Ns...>
{
using type = A<T, N2, Ns...>;
};
template <typename T, std::size_t ... Ns>
using PopFrontA_t = typename PopFrontA<T, Ns...>::type;
然后
// first implementation
template< size_t M = sizeof...(N_i)+1, typename std::enable_if< M!=1, size_t >::type = 0 >
PopFrontA_t<T, N, N_i...>
operator[]( size_t i )
{
A< T, N_i... > res{ /*...*/ };
return res;
}