英文:
Cannot pass struct to template function
问题
- 为什么
comp
在main
函数中不起作用,但在其他排序函数中起作用?
在您的 main
函数中,您创建了一个自定义比较结构体 Compare
,但问题出在比较运算符的定义上。在 Compare
结构体中,您定义的 operator()
返回 first.size() < sec.size()
,这意味着它将按字符串的长度升序排序。但是,您的排序函数期望的是一个降序排序(从长到短),因此 comp
在 main
函数中的使用与预期不符。
- 我该如何使这个代码按照我的意图工作?
如果您希望在 main
函数中使用 comp
对字符串按长度降序进行排序,您可以在 main
函数中使用 SortGreater
结构体,这样就能得到预期的结果。例如:
int main() {
vector<string> str = {"aa", "a", "aaa"};
vec::SortGreater<string> comp; // 使用 SortGreater 结构体
vec::sort(str, comp);
return 0;
}
这将使用 SortGreater
结构体,按字符串长度降序对 str
进行排序。
请确保您选择的比较结构体与排序方式一致,以获得预期的排序结果。
英文:
So I'm trying to create a sorting function that takes in an std::vector
and struct
and sorts the vector based on the struct. My code for the function is this:
template<typename T, typename C> void sort(vector<T> &array, C &comp) {
vector<T> blank(array.size(), 0);
mergeSort(array, blank, 0, array.size() - 1, comp);
}
The .cpp file is this:
#include "array.h"
#include <iostream>
#include <vector>
#include <string>
using namespace std;
struct Compare {
bool operator()(const string &first, const string &sec) {
return first.size() < sec.size();
}
};
int main() {
vector<string> str = {"aa", "a", "aaa"};
Compare comp;
vec::sort(str, comp);
return 0;
}
I tried this and many, many other variations of this code, but all of them end in error. This particular one says terminate called after throwing an instance of 'std::logic_error'
.
what(): basic_string: construction from null is not valid
The full code for "array.h"
is this:
#pragma once
#include <iostream>
#include <vector>
#include <cmath>
#include <string>
#include <ctime>
#include <cstdlib>
using namespace std;
/*
* Provides many algorithms and functions used with std::vector's
* @author M. Farnsworth
*/
namespace vec {
/*
* Sorts an std::vector either ascending or descending depending on ltog (least to greatest).
* If ltog is false it sorts the std::vector in descending.
* Is a proxy function between the user and the actuall sorting function.
* Implements the merge sort algorithm.
*/
template<typename T> void sort(vector<T> &array, bool ltog = true);
/*
* Sorts an std::vector based on the 'comp' given to it.
* Is a proxy function between the user and the actuall sorting function.
* Implements the merge sort algorithm.
* Overloads the first 'sort'.
*/
template<typename T, typename C> void sort(vector<T> &array, C &comp);
/*
* Second function in merge sort.
* Can be called by user directly, they will just need to provide values for the rest of the parameters.
* Don't call this function, call arr::sort(vector<int> &array, bool ltog) to sort.
*/
template<typename T, typename C> void mergeSort(vector<T> &array, vector<T> &blank, int bottom, int top, C &comp);
/*
* Third function in merge sort.
* Shouldn't be called by the user.
*/
template<typename T, typename C> void merge(vector<T> &array, vector<T> &copy, int bottom, int half, int top, C &comp);
/*
* Swaps items at the indices 'first' and 'second' of the given std::vector.
*/
template<typename T> void swap(vector<T> &array, int first, int second);
/*
* Reverses the order of the items in an std::vector.
*/
template<typename T> void reverse(vector<T> &array);
/*
* Writes the items in an std::vector to an std::ostream.
* Essentially this means it will display the array.
* If called with only the std::vector it will display to the console or 'cout' by default.
*/
template<typename T> void display(vector<T> &array, string diliminator = " ", bool endline = true, ostream &out = cout);
/*
* Provides a structor for comparing two T.
* operator() returns true if first is less than second.
* operator() returns false if first is greater or equal to second.
* Used in 'merge' to sort an std::vector in ascending order.
*/
template<typename T> struct SortLess;
/*
* Provides a structor for comparing two T.
* operator() returns false if first is less than second.
* operator() returns true if first is greater or equal to second.
* Used in 'merge' to sort an std::vector in descending order.
*/
template<typename T> struct SortGreater;
template<typename T> struct SortLess {
bool operator()(T &first, T &second) {
return first < second;
}
};
template<typename T> struct SortGreater {
bool operator()(T &first, T &second) {
return first > second;
}
};
template<typename T> void sort(vector<T> &array, bool ltog) {
vector<T> blank(array.size(), 0);
if (ltog) {
SortLess<T> comp;
mergeSort(array, blank, 0, array.size() - 1, comp);
} else {
SortGreater<T> comp;
mergeSort(array, blank, 0, array.size() - 1, comp);
}
}
template<typename T, typename C> void sort(vector<T> &array, C &comp) {
vector<T> blank(array.size(), 0);
mergeSort(array, blank, 0, array.size() - 1, comp);
}
template<typename T, typename C> void mergeSort(vector<T> &array, vector<T> &blank, int bottom, int top, C &comp) {
if (top != bottom) {
int half = bottom + (top - bottom) / 2;
mergeSort(array, blank, bottom, half, comp);
mergeSort(array, blank, half + 1, top, comp);
merge(array, blank, bottom, half, top, comp);
}
}
template<typename T, typename C> void merge(vector<T> &array, vector<T> &copy, int bottom, int half, int top, C &comp) {
for (int i = 0; i < array.size(); i++) {
copy[i] = array[i];
}
int firstCount = bottom;
int secCount = half + 1;
int count = firstCount;
while (firstCount <= half && secCount <= top) {
if (comp(copy[firstCount], copy[secCount])) {
array[count] = copy[firstCount];
firstCount++;
} else {
array[count] = copy[secCount];
secCount++;
}
count++;
}
for (int i = firstCount; i <= half; i++) {
array[count] = copy[i];
count++;
}
for (int i = secCount; i <= top; i++) {
array[count] = copy[i];
count++;
}
}
template<typename T> void swap(vector<T> &array, int first, int second) {
int temp = array[first];
array[first] = array[second];
array[second] = temp;
}
template<typename T> void reverse(vector<T> &array) {
int len = array.size();
for (int i = 0; i < ceil(len / 2.0); i++) {
swap(array, i, len - 1 - i);
}
}
template<typename T> void display(vector<T> &array, string diliminator, bool endline, ostream &out) {
for (int i = 0; i < array.size(); i++) {
out << array[i] << diliminator;
}
if (endline) out << endl;
}
template<typename T> void shuffle(vector<T> &array) {
srand(time(0));
for (int i = 0; i < array.size(); i++) {
int k = rand() % (i + 1);
swap(array, i, k);
}
}
};
So my question is two-fold:
- Why does the comp not work in main, but does int the other sort function?
- What can I do to make this work as I intend?
答案1
得分: 2
vector<T> blank(array.size(), 0);
这里你尝试创建一个大小为array.size()
的vector<T>
,但你想要用来复制到新的vector
中的std::string
是0
,这被解释为const char*
,并尝试从内存中的那个位置读取数据,这会导致_未定义的行为_,因为它尝试使用以下std::string
构造函数:
constexpr std::string(const char* s, const Allocator& alloc = Allocator());
为了用空的string
填充它,只需省略第二个参数:
vector<T> blank(array.size());
英文:
vector<T> blank(array.size(), 0);
Here you try to create a vector<string>
with the size array.size()
- but the std::string
that you want to use for copying into the new vector
is 0
, which is interpreted as a const char*
- and it tries to read from that place in memory with undefined behavior as a result using the std::string
constructor:
constexpr std::string(const char* s, const Allocator& alloc = Allocator() );
In order to populate it with empty string
s, simple leave the second argument out:
vector<T> blank(array.size());
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论