在模板中推断临时类型
Deduce type for temporary in template
我正在尝试使用模板创建一个通用的选择排序函数。
我做的是:
template<typename T>
void nrsort(T &a,int size)
{
// Applying Selection Sort
double temp; // This is the issue
for (int i = 0; i < size ; i++)
{
double minimum=a[i]; // This one too
for (int j = i+1; j < size ; j++)
{
if(a[j]<minimum)
{
temp=a[i];;
a[i]=a[j];
minimum=a[j];
a[j]=temp;
}
}
}
}
我想要一个可以对整数、浮点数、字符等进行排序的通用模板。
上面提到的代码有效,但主要问题是我对 double temp;
和 double minimum
进行了硬编码,并且每次都会进行数据转换。
如果我按如下方式编写 main
方法:
int main()
{
int values[]={4,3,6,1};
nrsort(values,4);
for (int i = 0; i < 4 ; i++)
{
cout<<values[i]<<"\t";
}
return 0;
}
那么在模板中推导出的类型 T
是 int [4]
一个由四个整数组成的数组。在函数内部,所有这些都转换为 double,代码工作正常。
但我的问题是,有什么方法可以让我不必将其硬编码为 double
并使用类似通用类型“T”的东西。
谢谢。
如果固定 temp
的范围,您可以简单地使用 auto
:
template<typename T>
void nrsort(T &a,int size)
{
// Applying Selection Sort
for (int i = 0; i < size ; i++)
{
auto minimum=a[i]; // This one too
for (int j = i+1; j < size ; j++)
{
if(a[j]<minimum)
{
auto temp=a[i];;
a[i]=a[j];
minimum=a[j];
a[j]=temp;
}
}
}
}
它会自动推断出正确的类型。
您的函数没有达到应有的通用性。解决此类问题的 STL 方法是使用 iterators。它将允许您对 C 风格的数组、std::vector
s 和任何其他提供随机访问迭代器的东西进行排序。你的函数应该采用一对像这样的迭代器:
template <typename IteratorT>
void
my_sort(IteratorT begin, IteratorT end);
然后,如果你#include <iterator>
,你可以像这样
查询值类型(即如果你取消引用一个IteratorT
你会得到什么)
using ValueT = typename std::iterator_traits<IteratorT>::value_type;
现在,ValueT
是您的类型的类型别名。
如果您愿意,可以提供一个方便的包装函数:
#include <utility> // for std::begin() and std::end()
template<typename ContainerT>
void
my_sort(ContainerT& container)
{
using std::begin;
using std::end;
my_sort(begin(container), end(container));
}
存在一个问题:这些函数模板会过于急切地匹配,即使迭代器不是随机访问迭代器。仅当 std::iterator_traits<IteratorT>::iterator_category
为 std::random_access_iterator_tag
时,您才可以使用 SFINAE 技巧来启用您的模板。或者您可以提供一个重载,将元素(或指向它们的指针/迭代器)复制到 std::vector
中,对其进行排序,然后将元素复制回来。有时,这是您能做的最好的事情。
我正在尝试使用模板创建一个通用的选择排序函数。
我做的是:
template<typename T>
void nrsort(T &a,int size)
{
// Applying Selection Sort
double temp; // This is the issue
for (int i = 0; i < size ; i++)
{
double minimum=a[i]; // This one too
for (int j = i+1; j < size ; j++)
{
if(a[j]<minimum)
{
temp=a[i];;
a[i]=a[j];
minimum=a[j];
a[j]=temp;
}
}
}
}
我想要一个可以对整数、浮点数、字符等进行排序的通用模板。
上面提到的代码有效,但主要问题是我对 double temp;
和 double minimum
进行了硬编码,并且每次都会进行数据转换。
如果我按如下方式编写 main
方法:
int main()
{
int values[]={4,3,6,1};
nrsort(values,4);
for (int i = 0; i < 4 ; i++)
{
cout<<values[i]<<"\t";
}
return 0;
}
那么在模板中推导出的类型 T
是 int [4]
一个由四个整数组成的数组。在函数内部,所有这些都转换为 double,代码工作正常。
但我的问题是,有什么方法可以让我不必将其硬编码为 double
并使用类似通用类型“T”的东西。
谢谢。
如果固定 temp
的范围,您可以简单地使用 auto
:
template<typename T>
void nrsort(T &a,int size)
{
// Applying Selection Sort
for (int i = 0; i < size ; i++)
{
auto minimum=a[i]; // This one too
for (int j = i+1; j < size ; j++)
{
if(a[j]<minimum)
{
auto temp=a[i];;
a[i]=a[j];
minimum=a[j];
a[j]=temp;
}
}
}
}
它会自动推断出正确的类型。
您的函数没有达到应有的通用性。解决此类问题的 STL 方法是使用 iterators。它将允许您对 C 风格的数组、std::vector
s 和任何其他提供随机访问迭代器的东西进行排序。你的函数应该采用一对像这样的迭代器:
template <typename IteratorT>
void
my_sort(IteratorT begin, IteratorT end);
然后,如果你#include <iterator>
,你可以像这样
IteratorT
你会得到什么)
using ValueT = typename std::iterator_traits<IteratorT>::value_type;
现在,ValueT
是您的类型的类型别名。
如果您愿意,可以提供一个方便的包装函数:
#include <utility> // for std::begin() and std::end()
template<typename ContainerT>
void
my_sort(ContainerT& container)
{
using std::begin;
using std::end;
my_sort(begin(container), end(container));
}
存在一个问题:这些函数模板会过于急切地匹配,即使迭代器不是随机访问迭代器。仅当 std::iterator_traits<IteratorT>::iterator_category
为 std::random_access_iterator_tag
时,您才可以使用 SFINAE 技巧来启用您的模板。或者您可以提供一个重载,将元素(或指向它们的指针/迭代器)复制到 std::vector
中,对其进行排序,然后将元素复制回来。有时,这是您能做的最好的事情。