[英]std::get like (partial) template specialization
I have class for complex numbers : 我上复数课:
template<typename T>
struct Complex{
T r;
T i;
};
I decided to add function similar to std::get
: 我决定添加类似于
std::get
函数:
template<int X, typename T>
T get(const Complex<T> &a){
switch(X){
case 0: return a.r;
case 1: return a.i;
}
}
This works OK. 这样就可以了。 Also I know the compiler can optimize it away.
我也知道编译器可以优化它。
Then I decided to rewrite it in different way: 然后,我决定以不同的方式重写它:
template<int X,typename T>
T get(const Complex<T> &a);
template<typename T>
constexpr T get<0, T>(const Complex<T> &a){
return a.r;
}
template<typename T>
constexpr T get<1, T>(const Complex<T> &a){
return a.i;
}
However this does not compile and I am curious how correct implementation will be? 但是,这无法编译,我很好奇实现的正确性如何?
I tried to check how std::get
is made, but I was unable to find anything that was "readable". 我试图检查
std::get
的制作方式,但是我找不到“可读”的东西。
In C++11 you can implement this exercise like: 在C ++ 11中,您可以像这样实现此练习:
#include <type_traits>
template<typename T>
struct Complex{
T r;
T i;
};
template<int X, typename T>
constexpr typename std::enable_if<X == 0,T>::type
get(const Complex<T> &a){
return a.r;
}
template<int X, typename T>
constexpr typename std::enable_if<X == 1,T>::type
get(const Complex<T> &a){
return a.i;
}
Partial template specialization is applicable for class templates, not function templates. 部分模板专门化适用于类模板,不适用于功能模板。
In C++14 you can write trivially more concise code using std::enable_if_t
. 在C ++ 14中,您可以使用
std::enable_if_t
编写更加简洁的代码。
And in C++17 you may use if constexpr
to write a single function template instead of SFINAE overloads. 在C ++ 17中,您可以使用
if constexpr
编写单个函数模板,而不是SFINAE重载。
Function templates cannot be partially specialised. 功能模板不能部分专门化。
Another method is tag dispatching that achieves a similar effect using function overloading: 另一种方法是标签分配 ,它使用函数重载可以达到类似的效果:
template<int X>
using Int = std::integral_constant<int, X>;
template<typename T> inline T get(const Complex<T> &a, Int<0>) { return a.r; }
template<typename T> inline T get(const Complex<T> &a, Int<1>) { return a.i; }
template<int X, typename T>
inline T get(const Complex<T> &a) { return get(a, Int<X>{}); }
I was able to come up with this, but it looks very complex for such an easy task: 我能够提出这个建议,但是对于这样一个简单的任务来说,它看起来非常复杂:
namespace complex_impl__{
template<int X, typename T>
struct GetHelper{
static T get(const Complex<T> &a);
};
template<typename T>
struct GetHelper<0, T>{
constexpr static T get(const Complex<T> &a){
return a.r;
}
};
template<typename T>
struct GetHelper<1, T>{
constexpr static T get(const Complex<T> &a){
return a.i;
}
};
}
template<int I,typename T>
constexpr T get(const Complex<T> &a){
return complex_impl__::GetHelper<I, T>::get(a);
}
Then I was able to move T
into get()
method, so I can make less code: 然后,我能够将
T
移到get()
方法中,因此可以减少代码量:
namespace complex_impl__{
template<int I>
struct GetHelper{
template<typename T>
static T get(const Complex<T> &a);
};
template<>
struct GetHelper<0>{
template<typename T>
constexpr static T get(const Complex<T> &a){
return a.r;
}
};
template<>
struct GetHelper<1>{
template<typename T>
constexpr static T get(const Complex<T> &a){
return a.i;
}
};
}
template<int I,typename T>
constexpr T get(const Complex<T> &a){
return complex_impl__::GetHelper<I>::get(a);
}
One may "strip" entire template<int I> struct GetHelper
class: 可以“剥离”整个
template<int I> struct GetHelper
类:
namespace complex_impl__{
template<int I>
struct GetHelper;
template<>
struct GetHelper<0>{
template<typename T>
constexpr static T get(const Complex<T> &a){
return a.r;
}
};
template<>
struct GetHelper<1>{
template<typename T>
constexpr static T get(const Complex<T> &a){
return a.i;
}
};
}
template<int I,typename T>
constexpr T get(const Complex<T> &a){
return complex_impl__::GetHelper<I>::get(a);
}
The problem is that you can't partially specialise function templates. 问题是您不能部分专门化功能模板。 Please read C++ template specialisation of function and Getting “illegal use of explicit template arguments” when doing a pointer partial specialization for a class method , which Nick describes the same solution of.
对类方法进行指针部分专业化时,请阅读函数的C ++模板专业化,以及“非法使用显式模板参数” ,尼克描述了相同的解决方案。
To get the template specialisation to work, please see Nick's answer. 要使模板专业化工作,请参阅Nick的答案。
Your solution does seem fine though, I would just change the switch into an if constexpr
. 但是,您的解决方案看起来还不错,我只是将开关更改为
if constexpr
。
#include <iostream>
template<typename T>
struct Complex
{
T r;
T i;
};
template<int X, typename T>
constexpr T get(const Complex<T> &a)
{
if constexpr(X == 0)
{
return a.r;
}
else if constexpr (X == 1)
{
return a.i;
}
}
int main()
{
Complex<int> test;
test.r = 1;
test.i = 12;
std::cout << get<0>(test) << std::endl;
std::cout << get<1>(test) << std::endl;
std::cin.get();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.