Я пытаюсь реализовать универсальный интерфейс с использованием языка PIMPL, для которого требуются некоторые функции-члены шаблона, чтобы обеспечить функциональность для типа ANY . Проблема в том, что я не могу найти какой-либо способ поддержки использования шаблонных функций с идиомой PIMPL без предварительного объявления всех возможных типов, которые может использовать функция.
См. Связанный вопрос: Идиома Pimpl с функцией-членом шаблона
Принятый ответ на этот вопрос предполагает явное определение каждого типа, который будет использоваться с шаблоном. Это не всегда практично. Рассмотрим следующий пример:
example.h
#ifndef EXAMPLE_H
#define EXAMPLE_H
#include <memory>
class Example
{
public:
Example();
~Example();
// Generic template function in the interface
template <typename T>
void PrintData(const T& data) const;
private:
struct Impl;
std::unique_ptr<Impl> m_impl;
};
#endif
example.cpp
#include "example.h"
#include <iostream>
// Private implementation
struct Example::Impl
{
template <typename T>
void PrintData(const T& data) const
{
std::cout << data << std::endl;
}
};
// Note: using C++11 so "make_unique" is not available
Example::Example() : m_impl(new Impl()) {}
Example::~Example() = default;
// Forward the method call to the implementation
template <typename T>
void Example::PrintData(const T& data) const
{
m_impl->PrintData(data);
}
// Don't want to have to explicitly state all types...
// this is not practical because "PrintData" should work for ANY printable type.
// Uncommenting the line below will allow this example to compile,
// but it will only compile when used with "int" data.
//template void Example::PrintData(const int& data) const;
main.cpp
#include "example.h"
int main()
{
Example ex;
ex.PrintData(42);
}
Попытка скомпилировать это не удастся с неопределенной ошибкой ссылки:
g++ -std=c++11 -o main main.cpp example.cpp
/tmp/cc6IhZsx.o: In function `main':
main.cpp:(.text+0x2b): undefined reference to `void Example::PrintData<int>(int const&) const'
collect2: error: ld returned 1 exit status
Этот пример предоставляет очень общую функцию в интерфейсе, которая должна работать для ЛЮБОГО печатного типа. Это создает проблему, поскольку мы не можем реально предсказать все типы, на которых эта функция будет использоваться до момента компиляции.
Как заставить такую функцию работать с идиомой PIMPL (или каким-либо другим способом создания " брандмауэра компилятора ")
Обратите внимание, что этот пример намеренно тривиален для демонстрации проблемы. В реальном мире у меня есть классы, которые содержат НАМНОГО более сложные шаблонные функции в интерфейсе, которые должны работать на многих типах. Из-за этого мне не удалось получить эти классы за брандмауэром компилятора, как обеспечивает идиома PIMPL.
Я открыт для рассмотрения альтернатив идиоме PIMPL, которые могут достичь желаемого эффекта, если такая вещь существует.