【问题标题】:function template specialization generating link error [duplicate]函数模板专业化生成链接错误[重复]
【发布时间】:2019-06-21 20:07:58
【问题描述】:

我之前问过this 的问题,涉及使用 auto 和生成元组的可变参数模板以及迭代它们的正确方法。用户metalfox 为我提供了this 解决方案。

我尝试了他们的解决方案,这就是我的完整代码的样子,包括我在原始代码中省略的命名空间。

calc.h

#include <algorithm>
#include <iostream>
#include <tuple>
#include <utility>

namespace math {

    template<class... T>
    class expression_t {
    public:
        std::tuple<T...> rhs;
        std::size_t size = sizeof...(T);

        //expression_t(const T&... args) : rhs{ args... } {}

        template <class... Args>
        expression_t(Args&& ...args) : rhs(std::forward<Args>(args)...) {}

        std::tuple<T...> operator()() const {
            return rhs;
        }
    };

    template<typename T>
    void Print(std::ostream& os, T x) {
        os << x;
    }

    template<>
    void Print<char>(std::ostream& os, char x) {
        if (x == '+' || x == '-' || x == '*' || x == '/' || x == '%')
            os << ' ' << x << ' ';
    }

    template<class... Args>
    expression_t<Args...> expression(Args... args) {
        expression_t<Args...> expr(args...);
        return expr;
    }

    template<class... Args>
    std::ostream& operator<<(std::ostream& os, const expression_t<Args...>& expr) {
        auto Fn = [&os](auto... x) {
            (Print(os, x), ...);
        };

        std::apply(Fn, expr.rhs);

        os << '\n';
        return os;
    }
}

ma​​in.cpp

#include "calc.h"

using namespace math;

int main() {
    double x = 0;    
    auto expr = expression(4, x, '^', 2, '+', 2, x);
    auto t = expr();
    std::cout << std::get<2>(t);
    std::cout << expr;
    return 0;
}

它在构建过程中生成此链接器错误:

1>------ Build started: Project: ChemLab, Configuration: Debug x64 ------
1>main.obj : error LNK2005: "void __cdecl math::Print<char>(class std::basic_ostream<char,struct std::char_traits<char> > &,char)" (??$Print@D@math@@YAXAEAV?$basic_ostream@DU?$char_traits@D@std@@@std@@D@Z) already defined in calc.obj
1>C:\***\test.exe : fatal error LNK1169: one or more multiply defined symbols found
1>Done building project "ChemLab.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

声明-定义这些打印函数以防止它们在单个翻译单元中被多次定义的正确方法是什么?

【问题讨论】:

  • 你在这个项目中还有其他包含calc.h的文件吗?
  • 错误信息提示calc.cpp还包括calc.h
  • @IgorTandetnik 你是对的,我确实有 calc.cpp,因为我在此处未显示的另一个嵌套命名空间内定义了其他函数。

标签: c++ templates c++17 linker-errors template-specialization


【解决方案1】:

函数模板特化——比如你的例子中的Print&lt;char&gt;——是一个常规函数,而不是一个模板。它必须只定义一次,否则使用 inline 关键字定义。

【讨论】:

  • 好的,我需要 inline 关键字。
  • 要么这样,要么在头文件中声明函数并在源文件中定义,就像您使用非模板函数一样。
  • 我尝试在 calc.cpp 中定义它,但仍然会产生链接错误。
  • 那你做错了。
  • @FrancisCugler 在cpp fie中定义的时候,头文件中还有专门化的声明吗?
猜你喜欢
  • 2013-12-27
  • 1970-01-01
  • 2020-07-25
  • 1970-01-01
  • 2017-12-10
  • 2011-10-29
  • 2011-07-24
  • 2011-10-06
相关资源
最近更新 更多