I am trying to combine the "pointer to implementation" (pImpl) idiom with variadic template arguments. However, I'm encountering a linker error, which I suspect might be due to a missing instantiation.
Here is a simplified version of my code:
foo.h
#pragma once
class Foo
{
public:
Foo();
template <class... Args>
int Method(Args&&... args);
private:
class Impl;
Impl* m_Impl;
};
foo.cpp
#include <utility>
#include "foo.h"
#include "impl.h"
Foo::Foo() :
m_Impl(new Foo::Impl())
{
}
template <class... Args>
int Foo::Method(Args&&... args)
{
return m_Impl->Method(std::forward<Args>(args)...);
}
impl.h
#pragma once
#include "foo.h"
class Foo::Impl
{
public:
int Method(int argc, char* argv[]);
};
impl.cpp
#include <iostream>
#include "impl.h"
int Foo::Impl::Method(int argc, char* argv[])
{
for (int i = 0; i < argc; ++i)
std::cout << argv[i] << std::endl;
return EXIT_SUCCESS;
}
main.cpp
#include "foo.h"
int main(int argc, char* argv[])
{
Foo foo;
return foo.Method(argc, argv);
}
My goal is to maintain the separation between Foo and Foo::Impl. However, the linker reports that it cannot find the symbol int Foo::Method<int&, char**&>(int&, char**&) (see example here). I've tried multiple method signatures to instantiate the missing symbol, but haven't been able to resolve the issue. There seems to be a subtlety in the way this is handled that I cannot fully understand. If the issue is indeed due to a missing instantiation, hopefully it can be resolved within the impl files to preserve the separation and avoid contaminating the foo files. Thank you!
Impl::Methodtakes exactly two parameters of known types, why isFoo::Methoda template (variadic or otherwise)? Why doesn't it take the same two parameters of the same types? Can you show an example whereFoo::Methodbeing a template makes something work that wouldn't work otherwise?std::vector<std::string>.Foo::Impl::Methodparameters of typesintandchar**are just examples. Imagine those can be anything, platform-specific, that I do not want to leak infoo.h.