Project

General

Profile

Is it really not mandatory to use DBO_EXTERN_TEMPLATES and DBO_INSTANTIATE_TEMPLATES?

Added by Ali Ali 9 days ago

I have read
https://redmine.emweb.be/boards/2/topics/4238
and
https://www.mail-archive.com/witty-interest@lists.sourceforge.net/msg06963.html
and a few others and I understand that using DBO_EXTERN_TEMPLATES and DBO_INSTANTIATE_TEMPLATES is to optimize compilation speed and in normal case there is no need to use them while my code does not compile without them. The error is as follows:

g++ ./build/./src/navigationBar.cpp.o ./build/./src/howToSolveSecion.cpp.o ./build/./src/Session.cpp.o ./build/./src/questionsSection.cpp.o ./build/./src/servicesSection.cpp.o ./build/./src/heroSection.cpp.o ./build/./src/User.cpp.o ./build/./src/footerSection.cpp.o ./build/./src/database/DbUser.cpp.o ./build/./src/main.cpp.o ./build/./src/MyAuthWidget.cpp.o -o out.wt -std=c++14 -lwthttp -lwt -lwtdbosqlite3 -lwtdbo
/usr/bin/ld: ./build/./src/main.cpp.o: in function void Wt::Dbo::persist<DbUser, void>::apply<Wt::Dbo::InitSchema>(DbUser&, Wt::Dbo::InitSchema&)':
main.cpp:(.text._ZN2Wt3Dbo7persistI6DbUservE5applyINS0_10InitSchemaEEEvRS2_RT_[_ZN2Wt3Dbo7persistI6DbUservE5applyINS0_10InitSchemaEEEvRS2_RT_]+0x23): undefined reference to
void DbUser::persistWt::Dbo::InitSchema(Wt::Dbo::InitSchema&)'
/usr/bin/ld: ./build/./src/main.cpp.o: in function void Wt::Dbo::persist<DbUser, void>::apply<Wt::Dbo::DropSchema>(DbUser&, Wt::Dbo::DropSchema&)':
main.cpp:(.text._ZN2Wt3Dbo7persistI6DbUservE5applyINS0_10DropSchemaEEEvRS2_RT_[_ZN2Wt3Dbo7persistI6DbUservE5applyINS0_10DropSchemaEEEvRS2_RT_]+0x23): undefined reference to
void DbUser::persistWt::Dbo::DropSchema(Wt::Dbo::DropSchema&)'
/usr/bin/ld: ./build/./src/main.cpp.o: in function void Wt::Dbo::persist<DbUser, void>::apply<Wt::Dbo::LoadDbAction<DbUser> >(DbUser&, Wt::Dbo::LoadDbAction<DbUser>&)':
main.cpp:(.text._ZN2Wt3Dbo7persistI6DbUservE5applyINS0_12LoadDbActionIS2_EEEEvRS2_RT_[_ZN2Wt3Dbo7persistI6DbUservE5applyINS0_12LoadDbActionIS2_EEEEvRS2_RT_]+0x23): undefined reference to
void DbUser::persistWt::Dbo::LoadDbAction >(Wt::Dbo::LoadDbAction&)'
/usr/bin/ld: ./build/./src/main.cpp.o: in function void Wt::Dbo::persist<DbUser, void>::apply<Wt::Dbo::SaveBaseAction>(DbUser&, Wt::Dbo::SaveBaseAction&)':
main.cpp:(.text._ZN2Wt3Dbo7persistI6DbUservE5applyINS0_14SaveBaseActionEEEvRS2_RT_[_ZN2Wt3Dbo7persistI6DbUservE5applyINS0_14SaveBaseActionEEEvRS2_RT_]+0x23): undefined reference to
void DbUser::persist
Wt::Dbo::SaveBaseAction(Wt::Dbo::SaveBaseAction&)'
/usr/bin/ld: ./build/./src/main.cpp.o: in function void Wt::Dbo::persist<DbUser, void>::apply<Wt::Dbo::SaveDbAction<DbUser> >(DbUser&, Wt::Dbo::SaveDbAction<DbUser>&)':
main.cpp:(.text._ZN2Wt3Dbo7persistI6DbUservE5applyINS0_12SaveDbActionIS2_EEEEvRS2_RT_[_ZN2Wt3Dbo7persistI6DbUservE5applyINS0_12SaveDbActionIS2_EEEEvRS2_RT_]+0x23): undefined reference to
void DbUser::persistWt::Dbo::SaveDbAction >(Wt::Dbo::SaveDbAction&)'
/usr/bin/ld: ./build/./src/main.cpp.o: in function void Wt::Dbo::persist<DbUser, void>::apply<Wt::Dbo::TransactionDoneAction>(DbUser&, Wt::Dbo::TransactionDoneAction&)':
main.cpp:(.text._ZN2Wt3Dbo7persistI6DbUservE5applyINS0_21TransactionDoneActionEEEvRS2_RT_[_ZN2Wt3Dbo7persistI6DbUservE5applyINS0_21TransactionDoneActionEEEvRS2_RT_]+0x23): undefined reference to
void DbUser::persist
Wt::Dbo::TransactionDoneAction(Wt::Dbo::TransactionDoneAction&)'

My codes are as follows:
DbUser.h :

#include <string>
#include <Wt/Dbo/Dbo.h>
#include <Wt/Dbo/backend/Sqlite3.h>
#include <Wt/Dbo/Session.h>
#include <Wt/Dbo/Transaction.h>
#include <Wt/Dbo/DbAction.h>
#include <Wt/Dbo/ptr.h>
#include <Wt/Dbo/SqlConnection.h>
#include <Wt/Dbo/Field.h>

class DbUser
{
private:
    /* data */
    std::string userName_;    
    std::string passwordHash_;

public:
    DbUser(/* args */);
    ~DbUser();

    template <class Action>
    void persist (Action& a);
};

DbUser.cpp :

#include "DbUser.hpp"
#include <Wt/Dbo/Dbo.h>


DbUser::DbUser(/* args */)
{
}

DbUser::~DbUser()
{
}

template <class Action>
void DbUser::persist (Action& a)
{

    Wt::Dbo::field (a, userName_, "username");
    Wt::Dbo::field (a, passwordHash_, "passwordHash");
}

main.c :


...

#include "database/DbUser.hpp"
#include <Wt/Dbo/Dbo.h>
#include <Wt/Dbo/backend/Sqlite3.h>
#include <Wt/Dbo/Session.h>
#include <Wt/Dbo/Transaction.h>
#include <Wt/Dbo/DbAction.h>
#include <Wt/Dbo/ptr.h>



class Test : public Wt::WApplication
{
private:
    /* data */
    void initDB (void);

public:
    Test (const Wt::WEnvironment &env);
    ~Test();
};

Test::Test (const Wt::WEnvironment &env) : Wt::WApplication(env)
{

...

}

Raha::~Raha()
{
}

void Test::initDB (void)
{

    auto sqlite3 = std::make_unique<Wt::Dbo::backend::Sqlite3>("myDB.db");
    Wt::Dbo::Session session;
    session.setConnection(std::move(sqlite3));

    session.mapClass<DbUser>("user");
    session.createTables();

}

int main (int argc, char **argv)
{

    return Wt::WRun (argc, argv, [](const Wt::WEnvironment &env){

        return (std::make_unique<Test>(env));
    });
}

Why my compiler can not instantiate the template code automatically?

My compiler is:

gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0


Replies (3)

RE: Is it really not mandatory to use DBO_EXTERN_TEMPLATES and DBO_INSTANTIATE_TEMPLATES? - Added by Matthias Van Ceulebroeck 9 days ago

It seems there is some cyclic including going on. It can be avoided, by not calling Wt/Dbo/Impl.h too soon.
Weirdly, Wt::Dbo::Dbo is part of Wt/Dbo/ptr.h. Whereas I would expect this in Wt/Dbo/Dbo.h.

This ought to be included in the header. If you want to specify class DbUser : public Wt::Dbo::Dbo<DbUser>.
In case you do not, you can just drop all Wt/Dbo inclusions in DbUser.h(pp).

That should resolve your compilation issue. I'll look a little further into this.

RE: Is it really not mandatory to use DBO_EXTERN_TEMPLATES and DBO_INSTANTIATE_TEMPLATES? - Added by Ali Ali 8 days ago

Actually, I added the all ‍‍Wt/Dbo inclusions in DbUser.h(pp) before finding DBO_EXTERN_TEMPLATES and DBO_INSTANTIATE_TEMPLATES to fix the problem. Anyway, I did what you said, but the problem still remains.

RE: Is it really not mandatory to use DBO_EXTERN_TEMPLATES and DBO_INSTANTIATE_TEMPLATES? - Added by Matthias Van Ceulebroeck 7 days ago

I apologize, I had performed other changes as well, that caused this to compile.

You can move the implementation of DbUser::persist to the header. Then it should all compile nicely.

    (1-3/3)