Как создать библиотеку, которая оборачивает объект с помощью функции шаблона, используя минимальные включения? - PullRequest
1 голос
/ 26 октября 2010

Целью этого проекта является создание библиотеки для распространения. В прошлом я использовал предварительные объявления, поэтому мне не приходилось распространять несколько заголовочных файлов вместе с библиотеками. Однако сейчас я пытаюсь устранить дублирование кода, переключаясь на шаблоны, и сталкиваюсь с некоторыми проблемами.

Во-первых, простой пример проекта, показывающий, что в данный момент работает:

//LibraryDep1.h

class LibraryDep1
{
public:
    LibraryDep1(void) {};
    virtual ~LibraryDep1(void) {};

    template <typename T>
    int TestFunction(T value)
    {
        std::cout << value << std::endl;
        return 0;
    }
};


//LibraryInclude.h

class LibraryDep1; //forward declare

class LibraryInclude
{
private:
    LibraryDep1* mLibDep1;
public:
    LibraryInclude(void);
    virtual ~LibraryInclude(void);

    int TestFunction(int value);
    int TestFunction(std::string value);


};

//LibraryInclude.cpp

#include "LibraryInclude.h"
#include "LibraryDep1.h"


LibraryInclude::LibraryInclude(void)
{
    this->mLibDep1 = new LibraryDep1();
}


LibraryInclude::~LibraryInclude(void)
{
    delete this->mLibDep1;
}

int LibraryInclude::TestFunction(int value)
{
    return this->mLibDep1->TestFunction(value);
}

int LibraryInclude::TestFunction(std::string value)
{
    return this->mLibDep1->TestFunction(value);
}

//main.cpp
#include <tchar.h>
#include "LibraryInclude.h"

int _tmain(int argc, _TCHAR* argv[])
{
    LibraryInclude inclLibrary;
    inclLibrary.TestFunction(77);
    inclLibrary.TestFunction("test");
}

Это дает ожидаемый результат:

77
test

Однако перегрузки LibraryInclude::TestFunction можно заменить функцией шаблона для дальнейшего уменьшения дублирования кода:

//LibraryInclude.h

class LibraryDep1; //forward declare

class LibraryInclude
{
private:
    LibraryDep1* mLibDep1;
public:
    LibraryInclude(void);
    virtual ~LibraryInclude(void);

    template <typename T>
    int TestFunction(T value) {
      return mLibDep1->TestFunction(value);
    }

};

Проблема сейчас в том, что я использую mLibDep1 без включения полной реализации, что дает мне неопределенную ошибку компиляции типа. Это означает, что мне нужно #include "LibraryDep1.h" в LibraryInclude.h, что потребует от меня распространения как LibraryInclude.h, так и LibraryDep1.h с моей библиотекой. Это простой пример, в реальном проекте есть много заголовочных файлов, которые нужно было бы распространять, если бы я переключился на использование шаблонной версии LibraryInclude.

Мой вопрос: есть ли способ избежать необходимости распространять связку включаемых файлов с моей библиотекой и устранить дублирование кода? Или мне лучше просто перегрузить все известные типы (радикально уменьшая гибкость библиотеки) в файле распределенного заголовка и оставить шаблоны только в базовых классах?

Ответы [ 2 ]

1 голос
/ 26 октября 2010

Очень ограниченным и уродливым решением будет:

//LibraryDep1.h

#pragma once
#include <iostream>

class LibraryDep1
{
public:
    LibraryDep1(void) {};
    virtual ~LibraryDep1(void) {};

    template <typename T>
    int TestFunction(T value)
    {
        std::cout << value << std::endl;
        return 0;
    }
};

//LibraryInclude.h

#pragma once

class LibraryDep1; //forward declare

class LibraryInclude
{
private:
   LibraryDep1* mLibDep1;

public:
    LibraryInclude(void);
    virtual ~LibraryInclude(void);

    template <typename T>
    int TestFunction(T value);
};

//LibraryInclude.cpp

#include "LibraryInclude.h"
#include "LibraryDep1.h"

#include <string>

LibraryInclude::LibraryInclude(void)
{
    mLibDep1 = new LibraryDep1();
}

LibraryInclude::~LibraryInclude(void)
{
}

// only to save some typing when only forwaring calls
#define LI_TESTFUNCTION( TYPE ) \
template<> \
int LibraryInclude::TestFunction<TYPE>( TYPE value ) {\
   return mLibDep1->TestFunction(value); \
}

// the allowed specializations, everything else causes link errors
LI_TESTFUNCTION( int );
LI_TESTFUNCTION( std::string );

Протестировано это с VC ++ 2k8 & g ++ 4.3.4, статически связывающим с LibraryInclude.o

1 голос
/ 26 октября 2010

Нет.В настоящее время нет способа делать то, что вы хотите.Когда поставщики компиляторов начнут реализовывать ключевое слово «export», вам повезет.В настоящее время я знаю только о комо, делающем это.Это ключевое слово существует уже много лет, поэтому я не буду затаить дыхание, пока остальные его не осуществят.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...