依赖于模板参数的成员函数实现
member function implementation depending on template parameter
我有以下问题:
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 ... ;
}
};
正如你在上面看到的,我尝试实现一个 class A
,它期望作为模板参数类型 T
(例如 int
或 float
) 和 sizeof...(N_i)+1
-许多 size_t
.
根据传递的数量size_t
(即sizeof...(N_i)+1
),我将对具有不同结果类型的成员函数operator[](size_t)
使用不同的实现:
sizeof...(N_i)+1 > 1
案例 return 类型 A < T, N_i... >
的一个实施
(在代码中称为"first implementation")
- 还有一个用于案例
sizeof...(N_i)+1 == 1
,return 类型 T
(在代码中称为 "second implementation")。
不幸的是,我不知道如何实现——上面的解决方案不起作用。有人有想法吗?
非常感谢。
如果修改
A< T, N_i... > res{ ... };
在
A< T, N_i... > res{ };
和
return ... ;
在
return T{} ;
还不够吗?
--- 编辑 ---
否:正如 Jarod42 所指出的(谢谢!),这还不够。
所以我提出以下解决方案,基于class模板专业化和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;
}
如果你不想专门化 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;
}
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;
}
我有以下问题:
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 ... ;
}
};
正如你在上面看到的,我尝试实现一个 class A
,它期望作为模板参数类型 T
(例如 int
或 float
) 和 sizeof...(N_i)+1
-许多 size_t
.
根据传递的数量size_t
(即sizeof...(N_i)+1
),我将对具有不同结果类型的成员函数operator[](size_t)
使用不同的实现:
sizeof...(N_i)+1 > 1
案例 return 类型A < T, N_i... >
的一个实施 (在代码中称为"first implementation")- 还有一个用于案例
sizeof...(N_i)+1 == 1
,return 类型T
(在代码中称为 "second implementation")。
不幸的是,我不知道如何实现——上面的解决方案不起作用。有人有想法吗?
非常感谢。
如果修改
A< T, N_i... > res{ ... };
在
A< T, N_i... > res{ };
和
return ... ;
在
return T{} ;
还不够吗?
--- 编辑 ---
否:正如 Jarod42 所指出的(谢谢!),这还不够。
所以我提出以下解决方案,基于class模板专业化和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;
}
如果你不想专门化 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;
}
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;
}