Addendum:
Let me simplify my question, to try this one step at a time, because I feel I've created too much confusion about what I'm trying to achieve.
Mind you, I'm using C++11 and I think I'm bound to using this when using the PHP-CPP library. But, as I'm a total beginner, I'm not even sure about this.
My ultimate goal would be to "simply" create a map that can hold any value that the template Php::Class
returns. But let's just start by trying a concrete one, for instance Php::Class<Animal::Mammal>
.
First, I create a class in the namespace Animal
called Mammal
, which extends from Php::Base
(when you want to export a class to PHP with PHP-CPP, it needs to extend Php::Base
):
namespace Animal {
class Mammal : public Php::Base { /* left out for brevity */ }
}
Then, to keep it simple, let me just try to create a map inside get_module()
for now and just try to add an element there:
extern "C"
{
PHPCPP_EXPORT void *get_module() {
// create the map
std::map<std::string, Php::Class<Animal::Mammal>> classMap;
// create the thing (at this point I just don't know what the actual return type is anymore) that will be exported later on.
Php::Class<Animal::Mammal> mammal( "Mammal" );
// try to add this "thing" to the map:
classMap[ "Animal::Mammal" ] = mammal;
/* left out for brevity */
}
This results in:
error: use of deleted function ‘Php::Class<Animal::Mammal>&
Php::Class<Animal::Mammal>::operator=(const Php::Class<Animal::Mammal>&)’
When I try:
// require a pointer
std::map<std::string, Php::Class<Animal::Mammal>*> classMap;
classMap[ "Animal::Mammal" ] = *mammal;
This results in:
error: no match for ‘operator*’ (operand type is ‘Php::Class<Animal::Mammal>’)
I've tried numerous other things as well, but nothing seem to allow me to put whatever the template Php::Class
creates into the map. I'm pulling my hair out, at this point. What am I missing?
Is it perhaps that the template Php::Class
creates something that simply cannot be put in a map? How do I find out what the thing is that the template Php::Class
actually creates?
Original question:
Although I have some cursory knowledge of C++, I'm new to actually programming with it.
I'm trying to develop a PHP extension with PHP-CPP. With this library you're able to define C++ classes and export them as PHP classes. Their documentation almost exclusively shows examples where you export those classes and methods inside it's main get_module()
function.
However, as this could get rather cluttered pretty quickly, I'd like to move this logic close to the individual classes instead. So, I've created a template function for this:
namespace Animal
{
template<typename T>
void addToExtension( Php::Extension &extension, Php::Namespace &ns, ClassMap &map ) { }
}
Which I then specialize with something like:
namespace Animal
{
class Mammal : public Php::Base
{
};
template<>
inline void addToExtension<Mammal>( Php::Extension &extension, Php::Namespace &ns, ClassMap &map ) {
Php::Class<Mammal> clss( "Mammal" );
// this is where I'm having extreme difficulty with
map[ "Animal::Mammal" ] = clss;
// add class to namespace
ns.add( std::move( clss ) );
}
}
...and in get_module()
I then do this:
PHPCPP_EXPORT void *get_module() {
static Php::Extension extension( "animals", "0.1" );
Php::Namespace ns( "Animal" );
Animal::ClassMap classMap;
Animal::addToExtension<Animal::Mammal>( extension, ns, classMap );
Animal::addToExtension<Animal::Dog>( extension, ns, classMap );
Animal::addToExtension<Animal::Cat>( extension, ns, classMap );
etc...
extension.add( std::move( ns ) );
return extension;
}
As you can see, I want to add each individual class to the Animal::ClassMap
map as well, because I want to use these when subsequent classes need to extend from them (for the export to PHP, that is):
// for instance, something like (not sure yet, if this is actually possible)
clss.extends( map[ "Animal::Mammal" ] );
But this is what I'm having extreme difficulties with. I've tried to define Animal::ClassMap
in all sorts of manners:
namespace Animal
{
// some examples of what I've tried:
typedef std::map<std::string, Php::Class> ClassMap;
typedef std::map<std::string, Php::Class*> ClassMap;
typedef std::map<std::string, Php::Base> ClassMap;
typedef std::map<std::string, Php::Base*> ClassMap;
typedef std::map<std::string, Php::ClassBase> ClassMap;
typedef std::map<std::string, Php::ClassBase*> ClassMap;
typedef std::map<std::string, Php::Class<Php::Base>> ClassMap;
typedef std::map<std::string, Php::Class<Php::Base>*> ClassMap;
typedef std::map<std::string, std::shared_ptr<Php::Class>> ClassMap;
// etc., etc., etc. ...
}
and tried to assign to it in all sorts of manners as well:
Php::Class<Mammal> clss( "Mammal" );
// some examples of what I've tried:
map[ "Animal::Mammal" ] = clss;
map[ "Animal::Mammal" ] = *clss;
map[ "Animal::Mammal" ] = &clss;
map[ "Animal::Mammal" ] = std::make_shared<Php::Class>( clss );
map[ "Animal::Mammal" ] = std::make_shared<Php::ClassBase>( clss );
map.insert( std::pair<std::string, Php::Class>( "Animal::Mammal", clss ) );
// etc., etc., etc. ...
but nothing compiles.
I've gotten compile errors ranging from "operator*
not defined", to "incomplete class" (or something to that effect), to "template argument is invalid".
As you can see, I clearly lack an actual understanding of what needs to be done here.
How do I determine what the proper value type for the map should be and how do I then properly add a "class" (is it even a proper class?) to the map?
PS: I'm fairly confident I've correctly included all necessary headers/files in the appropriate files. I've just omitted those in my examples for brevity.
It looks like
Php::Class
is a template, so you can't have it as themapped_type
of astd::map
, it isn't a type.You are going to have to have a "register me" function for each class you are registering, that goes into a collection.
If you have loads of namespaces to register, you may end up with a
std::map<std::string, std::vector<std::function<void(Php::Namespace &)>>>
, matching names to that namespaces collection of registration functions.You'd use that like