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

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

Cannot pass struct to template function

问题

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

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

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

如果您希望在 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&lt;typename T, typename C&gt; void sort(vector&lt;T&gt; &amp;array, C &amp;comp) {
    vector&lt;T&gt; blank(array.size(), 0);
    mergeSort(array, blank, 0, array.size() - 1, comp);
}

The .cpp file is this:

#include &quot;array.h&quot;
#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;string&gt;

using namespace std;

struct Compare {
    bool operator()(const string &amp;first, const string &amp;sec) {
      return first.size() &lt; sec.size();
    }  
};

int main() {
    vector&lt;string&gt; str = {&quot;aa&quot;, &quot;a&quot;, &quot;aaa&quot;};
    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 &#39;std::logic_error&#39;
what(): basic_string: construction from null is not valid
.

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

#pragma once
#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;cmath&gt;
#include &lt;string&gt;
#include &lt;ctime&gt;
#include &lt;cstdlib&gt;
using namespace std;


/*
* Provides many algorithms and functions used with std::vector&#39;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&lt;typename T&gt; void sort(vector&lt;T&gt; &amp;array, bool ltog = true);

    /*
    * Sorts an std::vector based on the &#39;comp&#39; given to it.
    * Is a proxy function between the user and the actuall sorting function.
    * Implements the merge sort algorithm.
    * Overloads the first &#39;sort&#39;.
    */
    template&lt;typename T, typename C&gt; void sort(vector&lt;T&gt; &amp;array, C &amp;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&#39;t call this function, call arr::sort(vector&lt;int&gt; &amp;array, bool ltog) to sort.
    */
    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);
    
    /*
    * Third function in merge sort.
    * Shouldn&#39;t be called by the user.
    */
    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);
    
    /*
    * Swaps items at the indices &#39;first&#39; and &#39;second&#39; of the given std::vector.
    */
    template&lt;typename T&gt; void swap(vector&lt;T&gt; &amp;array, int first, int second);

    /*
    * Reverses the order of the items in an std::vector.
    */
    template&lt;typename T&gt; void reverse(vector&lt;T&gt; &amp;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 &#39;cout&#39; by default.
    */
    template&lt;typename T&gt; void display(vector&lt;T&gt; &amp;array, string diliminator = &quot; &quot;, bool endline = true, ostream &amp;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 &#39;merge&#39; to sort an std::vector in ascending order.
    */
    template&lt;typename T&gt; 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 &#39;merge&#39; to sort an std::vector in descending order.
    */
    template&lt;typename T&gt; struct SortGreater;

    template&lt;typename T&gt; struct SortLess {
        bool operator()(T &amp;first, T &amp;second) {
            return first &lt; second;
        }
    };

    template&lt;typename T&gt; struct SortGreater {
        bool operator()(T &amp;first, T &amp;second) {
            return first &gt; second;
        }
    };

    template&lt;typename T&gt; void sort(vector&lt;T&gt; &amp;array, bool ltog) {
        vector&lt;T&gt; blank(array.size(), 0);
        if (ltog) {
            SortLess&lt;T&gt; comp;
            mergeSort(array, blank, 0, array.size() - 1, comp);
        } else {
            SortGreater&lt;T&gt; comp;
            mergeSort(array, blank, 0, array.size() - 1, comp);
        }
    }

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

    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) {
        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&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) {
        for (int i = 0; i &lt; array.size(); i++) {
            copy[i] = array[i];
        }
        
        int firstCount = bottom;
        int secCount = half + 1;
        int count = firstCount;
        
        while (firstCount &lt;= half &amp;&amp; secCount &lt;= top) {
            if (comp(copy[firstCount], copy[secCount])) {
                array[count] = copy[firstCount];
                firstCount++;
            } else {
                array[count] = copy[secCount];
                secCount++;
            }
            count++;
        }
        
        for (int i = firstCount; i &lt;= half; i++) {
            array[count] = copy[i];
            count++;
        }
        
        for (int i = secCount; i &lt;= top; i++) {
            array[count] = copy[i];
            count++;
        }
    }

    template&lt;typename T&gt; void swap(vector&lt;T&gt; &amp;array, int first, int second) {
        int temp = array[first];
        array[first] = array[second];
        array[second] = temp;
    }

    template&lt;typename T&gt; void reverse(vector&lt;T&gt; &amp;array) {
        int len = array.size();
        for (int i = 0; i &lt; ceil(len / 2.0); i++) {
            swap(array, i, len - 1 - i);
        }
    }

    template&lt;typename T&gt; void display(vector&lt;T&gt; &amp;array, string diliminator, bool endline, ostream &amp;out) {
        for (int i = 0; i &lt; array.size(); i++) {
            out &lt;&lt; array[i] &lt;&lt; diliminator;
        }
        if (endline) out &lt;&lt; endl;
    }
    
    template&lt;typename T&gt; void shuffle(vector&lt;T&gt; &amp;array) {
        srand(time(0));
        for (int i = 0; i &lt; array.size(); i++) {
            int k = rand() % (i + 1);
            swap(array, i, k);
        }
    }


};

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

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

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

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

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

vector<T> blank(array.size());
英文:
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:

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:

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:

确定