其他分享
首页 > 其他分享> > c – function …已经定义了一个body&function模板

c – function …已经定义了一个body&function模板

作者:互联网

我有这个头文件:

Utility.h:

#pragma once

#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <Windows.h>

using namespace std;

template<std::size_t> struct int_ {};

template <class Tuple, size_t Pos> 
std::ostream& print_tuple(std::ostream& out, const Tuple& t, int_<Pos>);

struct Timer {
public:
    Timer();
    void start();
    double getMilliSec();
private:
    LARGE_INTEGER frequency;        // ticks per second
    LARGE_INTEGER t1, t2;           // ticks
};

//...

#include "Utility.cpp"

而这个实现文件:

Utility.cpp:

#include "Utility.h"
template <class Tuple, size_t Pos>
std::ostream& print_tuple(std::ostream& out, const Tuple& t, int_<Pos>) {
     ...
}

Timer::Timer() {
    // get ticks per second
    QueryPerformanceFrequency(&frequency);
}

void Timer::start() {
    QueryPerformanceCounter(&t1);
}

double Timer::getMilliSec() {
    QueryPerformanceCounter(&t2);
    return (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart;
}

哪个返回此错误:

error C2995: 'std::ostream &print_tuple(std::ostream &,const Tuple &,int_<Pos>)': function template has already been defined
error C2084: function 'Timer::Timer(void)' already has a body
...

问题不在于警卫(如this问题所示),因为我使用#pragma一次

我已经阅读了关于模板类实现的implementing .tpp files,但我发现它是一个可怕的解决方案,因为Visual Studio将不会格式化此文件.

试图定义Utility.tpp :(错误的解决方案)

所以我用Utility.h中的#include“Utility.cpp with #include”Utility.tpp替换了…

Utility.tpp

Timer::Timer() {
    // get ticks per second
    QueryPerformanceFrequency(&frequency);
}

void Timer::start() {
    QueryPerformanceCounter(&t1);
}

double Timer::getMilliSec() {
    QueryPerformanceCounter(&t2);
    return (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart;
}

现在返回的错误是:

1>Memoization.obj : error LNK2005: "public: __cdecl Timer::Timer(void)" (??0Timer@@QEAA@XZ) already defined in HelloWorld.obj
...

这是主要的顺便说一下:

HelloWorld.cpp:

#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//#include "Memoization.cpp"
#include<vector>
#include"Utility.h"

using namespace std;

int main()
{
}

试图定义Utility.tpp :(正确的解决方案,最后)

正如在注释中注意到的那样,作为一个白痴,我在.tpp文件中导入了Time方法,显然我应该导入模板函数,因此在Utility.tpp中包含print_tuple,而Utility.cpp包含3个Timer函数.

解决方法:

如果要将cpp文件包含到头文件中,则需要在项目中排除该cpp文件.如果不这样,那么头文件将具有cpp文件所具有的内容,并且当编译器将cpp文件编译为对象时,您将拥有两个定义副本.一个在头文件中,因为它有一个cpp文件的副本,一个在cpp文件中,因为它实际上是编译的.这导致重新定义错误.

一旦从编译中删除Utility.cpp,那么包含Utility.h的任何其他cpp文件将具有完整源代码,因为还包括Utility.cpp.

要从编译中删除Utility.cpp,请参阅:How to exclude files from Visual Studio compile?

如果你使用cpp文件的唯一原因是因为tpp文件没有将C代码格式化为C,那么你可以配置MSVS将tpp文件视为C文件.如果你去工具 – >选项 – >文字编辑器 – >文件扩展名您可以为格式添加文件扩展名.在扩展框中输入扩展名,从编辑器下拉列表中选择Microsoft Visual C,然后单击“添加”.

现在您可以使用tpp文件而不是cpp文件,而不必记住从构建中排除cpp文件.您还可以遵循现代实践.

标签:c,templates,header-files
来源: https://codeday.me/bug/20191003/1850425.html