简体   繁体   中英

How to make a class member variable be the same type of return of a function template?

I am using a third party C++ library for sqlite orm. The library has a function that returns a template object. The type of the object is a very long template which depends on the number tables etc. That is why the examples provided always use auto . Here is an example:

auto storage = make_storage("db.sqlite",
                            make_table("users",
                                       make_column("id", &User::id, autoincrement(), primary_key()),
                                       make_column("first_name", &User::firstName),
                                       make_column("last_name", &User::lastName),
                                       make_column("birth_date", &User::birthDate),
                                       make_column("image_url", &User::imageUrl),
                                       make_column("type_id", &User::typeId)),
                            make_table("user_types",
                                       make_column("id", &UserType::id, autoincrement(), primary_key()),
                                       make_column("name", &UserType::name, default_value("name_placeholder"))));

The type of the storage object that is returned from the function is very long, something like this:

sqlite_orm::internal::storage_t<sqlite_orm::internal::table_t<Feed::MyClass, sqlite_orm::internal::column_t<Feed::MyClass, int, int const& (Feed::MyClass::*)() const, void (Feed::MyClass::*)(int), sqlite_orm::constraints::autoincrement ...

My question is that I would like to use this storage object as a member variable of another class. How would I tell the client class the return type of the function make_storage ?

You can use decltype(expr) to determine the type of an expression. To reasonably get hold of this type I'd package the query into a function with an auto result and use it to obtain the type for the member and later to actually do the queries:

template <typename... Args>
auto make_storage_query() {
    return make_storage("db.sqlite",
               make_table("users",
                          make_column("id", &User::id, autoincrement(), primary_key()),
                          make_column("first_name", &User::firstName),
                          make_column("last_name", &User::lastName),
                          make_column("birth_date", &User::birthDate),
                          make_column("image_url", &User::imageUrl),
                          make_column("type_id", &User::typeId)),
               make_table("user_types",
                          make_column("id", &UserType::id, autoincrement(), primary_key()),
                          make_column("name", &UserType::name, default_value("name_placeholder"))));
}

struct whatever {
    decltype(make_storage_query()) member;
}

int main() {
    whatever run{make_storage_query()};
}

Things get more interesting when your query needs arguments as you'll probably need to pass appropriate arguments to your query. If so, you'd need to come up with suitable arguments in for use with decltype(...) . As you may need variables which wouldn't be available in this context you'd probably use std::declval<T>() in place of an argument of type T , eg, std::declval<int&>() for an argument where a non- const variable of type int is passed. However, I haven't used the library you are referring to, ie, I don't know what's actually needed or whether it makes sense to use the return type as member.

How would I tell the client class the return type of the function make_storage?

Just ask the compiler!

Temporarily declare your variable/data attribute as something you know the return type is not, (and there are no conversions for it).

  • then read the error message from the compiler, and copy-paste the compiler's determination to the declaration.

The error message will report that it cannot find a conversion for the requested assignment.

If g++ description is confusing, try the same compile using clang++.


// auto - temporarily try int or some other type
int   storage = make_storage("db.sqlite",
                        make_table("users",
// the rest of it       ....
                        make_column("name", 
                           &UserType::name,
       default_value("name_placeholder"))));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM