I am getting a compilation error so clearly I am doing something wrong but I am not sure how to fix it nor if it is possible to have explicit instantiation and SFINAE. The reproducible example is minimal so it might not make complete sense but essentially there is a vector alike class that can be instantiated for unique_ptr or observer_ptr. The SFINAE part is to only allow for the add function to be available only for the unique_ptr.
I got a define there CompilationFail. It seems that if Bar has a FooPtrVectorView then I get an compilation error. If I dont define it then all is good. If I just use FooPtrVectorView say in a function (and not part of Bar) there are no issues.
The compiler error for msvc is error C3190: 'Foo *FooSmartPtrVector::add(void)' with the provided template arguments is not the explicit instantiation of any member function of 'FooSmartPtrVector'
For msvc users I have a zip file with the whole solution which might make it easier https://app.box.com/s/nzbgvxo58u4jmiw50o1hlh28yfyxo1d1
observer_ptr.h
template<typename T>
class observer_ptr
{
};
Foo.h and rest of implementation in .cpp
struct Foo{};
FooSmartPtrVector.h
#define CompilationFail 1
class Bar;
// this has to be forward declared in my case
struct Foo;
template<template<class...> class SmartPtr>
class FooSmartPtrVector
{
public:
#if CompilationFail
const Foo* fooBar(const Bar* const bar) const;
#endif
template<template<class...> class Q = SmartPtr,
typename std::enable_if_t<std::is_same<Q<Foo>, std::unique_ptr<Foo>>::value>* = nullptr>
Foo* add();
private:
std::vector<SmartPtr<Foo>> vec;
};
using FooPtrVectorView = FooSmartPtrVector<nonstd::observer_ptr>;
using FooPtrVector = FooSmartPtrVector<std::unique_ptr>;
FooSmartPtrVector.cpp
#include "FooSmartPtrVector.h"
#if CompilationFail
#include "Bar.h"
#endif
#if CompilationFail
template<template<class...> class SmartPtr>
const Foo* FooSmartPtrVector<SmartPtr>::fooBar(const Bar* const bar) const
{
return bar->getFromFooPtrView();
}
#endif
template<template<class...> class SmartPtr>
template<template<class...> class Q,
typename std::enable_if_t<std::is_same<Q<Foo>, std::unique_ptr<Foo>>::value>*>
Foo* FooSmartPtrVector<SmartPtr>::add()
{
auto uptr_foo = std::make_unique<Foo>();
auto foo = uptr_foo.get();
vec.emplace_back(std::move(uptr_foo));
return foo;
}
// explicit instantiations of our templates
template class FooSmartPtrVector<observer_ptr>;
template class FooSmartPtrVector<std::unique_ptr>;
template Foo* FooSmartPtrVector<std::unique_ptr>::add();
Bar.h
#include "FooSmartPtrVector.h"
struct Foo;
class Bar
{
public:
Foo* getFromFooPtrView() const { return nullptr; }
private:
bool isValid_;
FooPtrVectorView observations_vector_;
};
Any help is appreciated.