1

public/Interface.h

#pragma once

template <typename T>
class BaseInterface {
public:
    virtual void foo() = 0;
};

private/Base.h

#pragma once
#include "../public/Interface.h"

template <typename T>
class Base : public BaseInterface<T> {
public:
   virtual void foo() override;
};

template <typename T>
inline void Base<T>::foo() {
}

main.cpp

#include <iostream>
#include <memory>
#include "public/Interface.h"

int main() {
    auto base = std::make_shared< BaseInterface<std::string> >();
    base->foo();
    return 0;
}    

Getting this error:

/usr/include/c++/5/ext/new_allocator.h:120:4: error: invalid new-expression of abstract class type ‘BaseInterface<std::__cxx11::basic_string<char> >’
  { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }

AbstractPureVirtual/public/Interface.h:4:7: note:   because the following    virtual functions are pure within ‘BaseInterface<std::__cxx11::basic_string<char> >’:
 class BaseInterface {

AbstractPureVirtual/public/Interface.h:6:17: note:  void BaseInterface<T>::foo() [with T = std::__cxx11::basic_string<char>]
virtual void foo() = 0;

I get this error though I have overridden the pure virtual method in the Derived Class and seems like it is expected as its a template class. If I need to do something similar, how should I go about implementing this?

engg
  • 49
  • 3
  • No, that has nothing to do with the derived class -- the compiler doesn't even know about private/Base.h when compiling main.cpp – L. F. Jul 25 '18 at 02:28
  • Differently phrased [question](https://stackoverflow.com/questions/24968294/how-to-make-shared-a-derived-class) with essentially the same answer. – 1201ProgramAlarm Jul 25 '18 at 02:36
  • Did you mean `std::make_shared< Base>()` ? How the compiler would know which derived class to call to construct the interface class ? – Jarod42 Jul 25 '18 at 08:08

2 Answers2

1

make_shared creates an object of exactly the class you specified. It is unable to know its derived classes, so make_shared< BaseInterface<std::string> >() essentially invokes new BaseInterface<std::string>, and creating object of an abstract class is not allowed. This has nothing to do with the templates; the error is still there if you replace them with ordinary classes.

L. F.
  • 19,445
  • 8
  • 48
  • 82
0
auto base = std::make_shared< BaseInterface<std::string> >();

you tried to create a concrete object of type BaseInterface<std::string> here. I suspect you want:

auto base = std::make_shared< Base<std::string> >();

or maybe

std::shared_ptr< BaseInterface<std::string> > base = std::make_shared< Base<std::string> >();
Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • This indeed is more reasonable. – L. F. Jul 25 '18 at 02:34
  • Thanks for your response L. F. and Yakk. I understand why this will not work. What I am trying to do here is to hide the implementation details of concrete class and just provide an interface to the application linking against this library. What is the best way to approach this? – engg Jul 25 '18 at 07:16
  • @engg Libraries cannot export templates. There are ways of exporting type erased things that act somewhat like exporting templates, but they are weaker in specific ways, and your abstract ask does not detail the ways you can accept something weaker than templates. This is a common kind of X/Y problem; in order to get an answer you may have to ask another question with a concrete problem case. Or accept "no". – Yakk - Adam Nevraumont Jul 25 '18 at 10:50