You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用CppUnit测试基于模板的array<int,N>归并排序函数?

解决C++模板归并排序的CppUnit链接错误

问题根源

C++模板采用编译期实例化机制:模板函数的实现代码必须在调用它的编译单元(.cpp文件)中可见,编译器才能生成对应类型/大小的模板实例。

你将模板函数的实现放在了mergeSortByMyself.cpp中,测试代码testing.cpp仅包含头文件的声明。编译测试代码时,编译器无法生成size_t=12(测试中用到的数组大小)对应的模板实例,导致链接阶段找不到函数定义。

而单独运行main时能正常工作,是因为main所在的编译单元在编译时能看到模板实现,自动实例化了需要的版本。

解决方案

有两种常用修复方式:

方法1:将模板实现移到头文件中

直接把mergeSortByMyself.cpp里的所有模板函数实现,迁移到mergeSortModel.h(注意统一文件名:你的头文件代码写的是mergeModel.h,但实现/测试文件引用的是mergeSortModel.h,需保持一致)中,和声明放在一起。

修改后的mergeSortModel.h示例:

#pragma once
#include <bits/stdc++.h>
using namespace std;

template<typename Iterator>
void print(Iterator list){
    for(auto item: list ){
        cout << item << " ";
    }
    cout << endl;
}

template<size_t M, size_t P>
array<int,M+P> merge(array<int,M>& arr1, array<int,P>& arr2){
    cout << "Merge starts here......."<<endl;
    int i = 0, j = 0, k = 0;
    array<int,arr1.size()+arr2.size()> joined;
    cout << "a1: " << arr1.size() << " a2: "<< arr2.size() << " a3: "<<joined.size()<< endl;
    for(k = 0; k < joined.size(); k++){
        if(i < arr1.size() && j < arr2.size() && arr1[i] < arr2[j]){
            joined[k] = arr1[i];
            i++;
        }else if( i < arr1.size() && j < arr2.size() &&  arr1[i] > arr2[j]){
            joined[k] = arr2[j];
            j++;
        }else{
            break;
        }
    }
    
    if(i == arr1.size()){
        for(; k < joined.size();k++  ){
            joined[k] = arr2[j];
            j++;
        }
    }
    if(j == arr2.size()){
        for(; k < joined.size(); k++){
            joined[k] = arr1[i];
            i++;
        }
    }
    cout << "joined ";
    print(joined);  
    return joined;
}

template<size_t N>
array<int,N> mergeSortByMyself(array<int,N>& list){
    if(list.size() <= 1){
        return list;
    }
    const int firstPart = (const int)list.size()/2;
    array<int, firstPart> leftArr;
    int i;
    for(i=0; i < firstPart; i++){
        leftArr[i] = list[i];
    }
    array<int,list.size() - firstPart> rightArr;
    for(i=firstPart; i < list.size(); i++){
        rightArr[i-firstPart] = list[i];
    }
    print(list);
    print(leftArr);
    print(rightArr);

    leftArr = mergeSortByMyself(leftArr);
    rightArr = mergeSortByMyself(rightArr);

    array<int,list.size()> joined;
    if(leftArr[leftArr.size() -1] > rightArr[0]){
        joined = merge(leftArr,rightArr);
    }else{
        int y = 0;
        for(int g = 0; g < joined.size(); g++){
            if(y < leftArr.size()){
                joined[g] = leftArr[y];
            }else{
                joined[g] = rightArr[y-leftArr.size()];
            }
            y++;
        }
    }
    return joined;
}

之后删除mergeSortByMyself.cpp,保持原编译命令即可:

g++ testing.cpp -lcppunit -o test

方法2:显式实例化模板

若不想移动实现代码,可在mergeSortByMyself.cpp末尾显式实例化测试需要的所有模板版本:

// 在mergeSortByMyself.cpp最后添加
template array<int,12> mergeSortByMyself(array<int,12>&);
template array<int,6> mergeSortByMyself(array<int,6>&);
template array<int,3> mergeSortByMyself(array<int,3>&);
template array<int,1> mergeSortByMyself(array<int,1>&);
template array<int,6+6> merge(array<int,6>&, array<int,6>&);
template array<int,3+3> merge(array<int,3>&, array<int,3>&);
template void print(array<int,12>&);
template void print(array<int,6>&);
// 其他用到的模板实例都需要显式声明

这种方法灵活性差,每次测试不同大小的数组都需手动添加对应实例。

额外修复点

测试代码中的断言逻辑错误:当前断言是将排序后的数组和原始未排序数组比较,应改为和你的归并排序结果比较:

// 原错误代码
CPPUNIT_ASSERT(toStr(tosort)==toStr(tosort_test));
// 修改为
CPPUNIT_ASSERT(toStr(tosort)==toStr(sorted));

内容的提问来源于stack exchange,提问作者matt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 12:10:55