无法将结构体传递给模板函数。

huangapple go评论97阅读模式
英文:

Cannot pass struct to template function

问题

  1. 为什么 compmain 函数中不起作用,但在其他排序函数中起作用?

在您的 main 函数中,您创建了一个自定义比较结构体 Compare,但问题出在比较运算符的定义上。在 Compare 结构体中,您定义的 operator() 返回 first.size() < sec.size(),这意味着它将按字符串的长度升序排序。但是,您的排序函数期望的是一个降序排序(从长到短),因此 compmain 函数中的使用与预期不符。

  1. 我该如何使这个代码按照我的意图工作?

如果您希望在 main 函数中使用 comp 对字符串按长度降序进行排序,您可以在 main 函数中使用 SortGreater 结构体,这样就能得到预期的结果。例如:

  1. int main() {
  2. vector<string> str = {"aa", "a", "aaa"};
  3. vec::SortGreater<string> comp; // 使用 SortGreater 结构体
  4. vec::sort(str, comp);
  5. return 0;
  6. }

这将使用 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:

  1. template&lt;typename T, typename C&gt; void sort(vector&lt;T&gt; &amp;array, C &amp;comp) {
  2. vector&lt;T&gt; blank(array.size(), 0);
  3. mergeSort(array, blank, 0, array.size() - 1, comp);
  4. }

The .cpp file is this:

  1. #include &quot;array.h&quot;
  2. #include &lt;iostream&gt;
  3. #include &lt;vector&gt;
  4. #include &lt;string&gt;
  5. using namespace std;
  6. struct Compare {
  7. bool operator()(const string &amp;first, const string &amp;sec) {
  8. return first.size() &lt; sec.size();
  9. }
  10. };
  11. int main() {
  12. vector&lt;string&gt; str = {&quot;aa&quot;, &quot;a&quot;, &quot;aaa&quot;};
  13. Compare comp;
  14. vec::sort(str, comp);
  15. return 0;
  16. }

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 &#39;std::logic_error&#39;
what(): basic_string: construction from null is not valid
.

The full code for &quot;array.h&quot; is this:

  1. #pragma once
  2. #include &lt;iostream&gt;
  3. #include &lt;vector&gt;
  4. #include &lt;cmath&gt;
  5. #include &lt;string&gt;
  6. #include &lt;ctime&gt;
  7. #include &lt;cstdlib&gt;
  8. using namespace std;
  9. /*
  10. * Provides many algorithms and functions used with std::vector&#39;s
  11. * @author M. Farnsworth
  12. */
  13. namespace vec {
  14. /*
  15. * Sorts an std::vector either ascending or descending depending on ltog (least to greatest).
  16. * If ltog is false it sorts the std::vector in descending.
  17. * Is a proxy function between the user and the actuall sorting function.
  18. * Implements the merge sort algorithm.
  19. */
  20. template&lt;typename T&gt; void sort(vector&lt;T&gt; &amp;array, bool ltog = true);
  21. /*
  22. * Sorts an std::vector based on the &#39;comp&#39; given to it.
  23. * Is a proxy function between the user and the actuall sorting function.
  24. * Implements the merge sort algorithm.
  25. * Overloads the first &#39;sort&#39;.
  26. */
  27. template&lt;typename T, typename C&gt; void sort(vector&lt;T&gt; &amp;array, C &amp;comp);
  28. /*
  29. * Second function in merge sort.
  30. * Can be called by user directly, they will just need to provide values for the rest of the parameters.
  31. * Don&#39;t call this function, call arr::sort(vector&lt;int&gt; &amp;array, bool ltog) to sort.
  32. */
  33. template&lt;typename T, typename C&gt; void mergeSort(vector&lt;T&gt; &amp;array, vector&lt;T&gt; &amp;blank, int bottom, int top, C &amp;comp);
  34. /*
  35. * Third function in merge sort.
  36. * Shouldn&#39;t be called by the user.
  37. */
  38. template&lt;typename T, typename C&gt; void merge(vector&lt;T&gt; &amp;array, vector&lt;T&gt; &amp;copy, int bottom, int half, int top, C &amp;comp);
  39. /*
  40. * Swaps items at the indices &#39;first&#39; and &#39;second&#39; of the given std::vector.
  41. */
  42. template&lt;typename T&gt; void swap(vector&lt;T&gt; &amp;array, int first, int second);
  43. /*
  44. * Reverses the order of the items in an std::vector.
  45. */
  46. template&lt;typename T&gt; void reverse(vector&lt;T&gt; &amp;array);
  47. /*
  48. * Writes the items in an std::vector to an std::ostream.
  49. * Essentially this means it will display the array.
  50. * If called with only the std::vector it will display to the console or &#39;cout&#39; by default.
  51. */
  52. template&lt;typename T&gt; void display(vector&lt;T&gt; &amp;array, string diliminator = &quot; &quot;, bool endline = true, ostream &amp;out = cout);
  53. /*
  54. * Provides a structor for comparing two T.
  55. * operator() returns true if first is less than second.
  56. * operator() returns false if first is greater or equal to second.
  57. * Used in &#39;merge&#39; to sort an std::vector in ascending order.
  58. */
  59. template&lt;typename T&gt; struct SortLess;
  60. /*
  61. * Provides a structor for comparing two T.
  62. * operator() returns false if first is less than second.
  63. * operator() returns true if first is greater or equal to second.
  64. * Used in &#39;merge&#39; to sort an std::vector in descending order.
  65. */
  66. template&lt;typename T&gt; struct SortGreater;
  67. template&lt;typename T&gt; struct SortLess {
  68. bool operator()(T &amp;first, T &amp;second) {
  69. return first &lt; second;
  70. }
  71. };
  72. template&lt;typename T&gt; struct SortGreater {
  73. bool operator()(T &amp;first, T &amp;second) {
  74. return first &gt; second;
  75. }
  76. };
  77. template&lt;typename T&gt; void sort(vector&lt;T&gt; &amp;array, bool ltog) {
  78. vector&lt;T&gt; blank(array.size(), 0);
  79. if (ltog) {
  80. SortLess&lt;T&gt; comp;
  81. mergeSort(array, blank, 0, array.size() - 1, comp);
  82. } else {
  83. SortGreater&lt;T&gt; comp;
  84. mergeSort(array, blank, 0, array.size() - 1, comp);
  85. }
  86. }
  87. template&lt;typename T, typename C&gt; void sort(vector&lt;T&gt; &amp;array, C &amp;comp) {
  88. vector&lt;T&gt; blank(array.size(), 0);
  89. mergeSort(array, blank, 0, array.size() - 1, comp);
  90. }
  91. template&lt;typename T, typename C&gt; void mergeSort(vector&lt;T&gt; &amp;array, vector&lt;T&gt; &amp;blank, int bottom, int top, C &amp;comp) {
  92. if (top != bottom) {
  93. int half = bottom + (top - bottom) / 2;
  94. mergeSort(array, blank, bottom, half, comp);
  95. mergeSort(array, blank, half + 1, top, comp);
  96. merge(array, blank, bottom, half, top, comp);
  97. }
  98. }
  99. template&lt;typename T, typename C&gt; void merge(vector&lt;T&gt; &amp;array, vector&lt;T&gt; &amp;copy, int bottom, int half, int top, C &amp;comp) {
  100. for (int i = 0; i &lt; array.size(); i++) {
  101. copy[i] = array[i];
  102. }
  103. int firstCount = bottom;
  104. int secCount = half + 1;
  105. int count = firstCount;
  106. while (firstCount &lt;= half &amp;&amp; secCount &lt;= top) {
  107. if (comp(copy[firstCount], copy[secCount])) {
  108. array[count] = copy[firstCount];
  109. firstCount++;
  110. } else {
  111. array[count] = copy[secCount];
  112. secCount++;
  113. }
  114. count++;
  115. }
  116. for (int i = firstCount; i &lt;= half; i++) {
  117. array[count] = copy[i];
  118. count++;
  119. }
  120. for (int i = secCount; i &lt;= top; i++) {
  121. array[count] = copy[i];
  122. count++;
  123. }
  124. }
  125. template&lt;typename T&gt; void swap(vector&lt;T&gt; &amp;array, int first, int second) {
  126. int temp = array[first];
  127. array[first] = array[second];
  128. array[second] = temp;
  129. }
  130. template&lt;typename T&gt; void reverse(vector&lt;T&gt; &amp;array) {
  131. int len = array.size();
  132. for (int i = 0; i &lt; ceil(len / 2.0); i++) {
  133. swap(array, i, len - 1 - i);
  134. }
  135. }
  136. template&lt;typename T&gt; void display(vector&lt;T&gt; &amp;array, string diliminator, bool endline, ostream &amp;out) {
  137. for (int i = 0; i &lt; array.size(); i++) {
  138. out &lt;&lt; array[i] &lt;&lt; diliminator;
  139. }
  140. if (endline) out &lt;&lt; endl;
  141. }
  142. template&lt;typename T&gt; void shuffle(vector&lt;T&gt; &amp;array) {
  143. srand(time(0));
  144. for (int i = 0; i &lt; array.size(); i++) {
  145. int k = rand() % (i + 1);
  146. swap(array, i, k);
  147. }
  148. }
  149. };

So my question is two-fold:

  1. Why does the comp not work in main, but does int the other sort function?
  2. What can I do to make this work as I intend?

答案1

得分: 2

  1. vector<T> blank(array.size(), 0);

这里你尝试创建一个大小为array.size()vector<T>,但你想要用来复制到新的vector中的std::string0,这被解释为const char*,并尝试从内存中的那个位置读取数据,这会导致_未定义的行为_,因为它尝试使用以下std::string构造函数:

  1. constexpr std::string(const char* s, const Allocator& alloc = Allocator());

为了用空的string填充它,只需省略第二个参数:

  1. vector<T> blank(array.size());
英文:
  1. vector&lt;T&gt; blank(array.size(), 0);

Here you try to create a vector&lt;string&gt; 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:

  1. constexpr std::string(const char* s, const Allocator&amp; alloc = Allocator() );

In order to populate it with empty strings, simple leave the second argument out:

  1. vector&lt;T&gt; blank(array.size());

huangapple
  • 本文由 发表于 2023年2月24日 00:58:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/75547979.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定