C++ template specialization definitions shared across files

穿精又带淫゛_ 提交于 2021-01-27 07:05:31

问题


I have a template class "Extra," defined in "extra.h," with a function "doSomething," and I have defined two specializations of "doSomething." Two different functions create objects of type "Extra," each with a different type parameter, and each calls a different one of the specializations. The two client functions, "client1" and "client2," are defined in two files, "client1.cpp" and "client2.cpp," respectively. In a third file, "main" calls "client1" and then "client2." Now, "client1.cpp" and "client2.cpp" both #include "extra.h." I get a linker error that "doSomething" has (2) multiple definitions. Naturally, if I put the defintions of "client1" and "client2" into a single source file, I do not have this problem. Is there any way that I can preserve my arrangement of distinct files for "client1" and "client2"? Below is my code. Thank you!

// extra.h
#ifndef EXTRA_H
#define EXTRA_H

template <typename T>
class Extra
{
    public:
        Extra(T);
        ~Extra();
        T doSomething(T);
    private:
        Extra() {}
        T m_value;
};

template <typename T> Extra<T>::Extra(T input) : m_value{input} {}

template <typename T> Extra<T>::~Extra() {}

template <> int Extra<int>::doSomething(int input)
{
    return input * m_value;
}

template <> double Extra<double>::doSomething(double input)
{
    return input + m_value;
}

template <typename T> T Extra<T>::doSomething(T input)
{
    return input;
}
#endif

// client1.cpp
#include "extra.h"
#include <iostream>

void client1()
{
    std::cout << "In client1." << std::endl;
    Extra<int> extra(2);
    int res = extra.doSomething(3);
    std::cout << "Value: " << res << std::endl;
}

// client2.cpp
#include "extra.h"
#include <iostream>

void client2()
{
    std::cout << "In client2." << std::endl;
    Extra<double> extra(2.0);
    double res = extra.doSomething(2.0);
    std::cout << "Value: " << res << std::endl;
}

// main.cpp
#include <iostream>

void client1();
void client2();

int main()
{
    std::cout << "In main." << std::endl;
    client1();
    client2();
    return 0;
}

And here, for completness, is my linker error:

$ g++ -std=c++11 -o client client1.cpp client2.cpp main.cpp 
duplicate symbol __ZN5ExtraIiE11doSomethingEi in:
    /var/folders/mf/jdvfkpms609206zpz8x5237r0000gn/T/client1-6fa7ed.o
    /var/folders/mf/jdvfkpms609206zpz8x5237r0000gn/T/client2-387444.o
duplicate symbol __ZN5ExtraIdE11doSomethingEd in:
    /var/folders/mf/jdvfkpms609206zpz8x5237r0000gn/T/client1-6fa7ed.o
    /var/folders/mf/jdvfkpms609206zpz8x5237r0000gn/T/client2-387444.o
ld: 2 duplicate symbols for architecture x86_64

回答1:


You need to mark your doSomething inline:

template <> inline int Extra<int>::doSomething(int input)
{
    return input * m_value;
}

template <> inline double Extra<double>::doSomething(double input)
{
    return input + m_value;
}


来源:https://stackoverflow.com/questions/44081844/c-template-specialization-definitions-shared-across-files

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!