Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gcc 6.1.1 compiling problem about 'does not match any template declaration' #55

Closed
semsevens opened this issue Jul 5, 2016 · 7 comments

Comments

@semsevens
Copy link
Contributor

semsevens commented Jul 5, 2016

The library works well when I use Fedora 23 whose gcc's version is gcc-c++-5.3.1-6.fc23.x86_64.rpm.
But after I updated to Fedora 24 in which gcc's version is gcc-c++-6.1.1-3.fc24.x86_64.rpm, the problem occurred.

When I compiling my project, It shows:

In file included from nb.cc:5:0:
/usr/local/include/sqlite_modern_cpp.h:494:25: error: template-id ‘get_col_from_db<>for ‘void sqlite::get_col_from_db(sqlite::database_binder&, int, std::__cxx11::string&)’ does not match any template declaration
  template<> inline void get_col_from_db(database_binder& db, int inx, std::string & s) {
                         ^~~~~~~~~~~~~~~
/usr/local/include/sqlite_modern_cpp.h:454:35: note: candidates are: template<class T> void sqlite::get_col_from_db(sqlite::database_binder&, int, std::vector<Type>&)
  template<typename T> inline void get_col_from_db(database_binder& db, int inx, std::vector<T>& vec) {
                                   ^~~~~~~~~~~~~~~
/usr/local/include/sqlite_modern_cpp.h:483:35: note:                 template<class T> void sqlite::get_col_from_db(sqlite::database_binder&, int, std::unique_ptr<T>&)
  template<typename T> inline void get_col_from_db(database_binder& db, int inx, std::unique_ptr<T>& _ptr_) {
                                   ^~~~~~~~~~~~~~~
/usr/local/include/sqlite_modern_cpp.h:507:37: error: template-id ‘operator<< <>for ‘sqlite::database_binder& sqlite::operator<<(sqlite::database_binder&, const string&)’ does not match any template declaration
  template<> inline database_binder& operator <<(database_binder& db, const std::string& txt) {
                                     ^~~~~~~~
/usr/local/include/sqlite_modern_cpp.h:444:47: note: candidates are: template<class T> sqlite::database_binder& sqlite::operator<<(sqlite::database_binder&, const std::vector<Type>&)
  template<typename T> inline database_binder& operator<<(database_binder& db, const std::vector<T>& vec) {

I'm very confused.
After I reading this article -- Why Not Specialize Function Templates?, I think it may due to the specialized function templates.
So I replace all specialized function templates with nontemplate functions and add them to be friends of class database_binder in file /usr/local/include/sqlite_modern_cpp.h.
And then it works.
Although this solved my problem, but I think it may be not the best way.
Here is my solution: Comparing changes

@aminroosta
Copy link
Collaborator

@semsevens Thanks for reporting this, i will install gcc-6.1 and try to reproduce this.
About your solution are you sure you want to delete this line?

@aminroosta aminroosta mentioned this issue Jul 5, 2016
@aminroosta
Copy link
Collaborator

@semsevens Thanks for the article, i think gcc6 is not happy with those function overloading rules!
I think your solution to overload non-template functions instead of specializing them is absolutely right 🏆

I've merged with your fork first ( i hope you don't mind :-) ) and then made sure all our tests pass with gcc-5, gcc-6 & clang.

I hope MSVC doesn't complain about this, which shouldn't.

@semsevens
Copy link
Contributor Author

@aminroosta ,
If I don't delete this line in /usr/local/include/sqlite_modern_cpp.h:

366         get_col_from_db(db, sizeof...(Values), value);

I will get following errors:

/usr/local/include/sqlite_modern_cpp.h:366: undefined reference to `void sqlite::get_col_from_db<bool>(sqlite::database_binder&, int, bool&)'
/tmp/ccqEtE2a.o: In function `std::enable_if<(sizeof (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, bool, bool, bool))<(10ul), void>::type sqlite::binder<10ul>::run<Data::SetCalendars()::{lambda(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, bool, bool, bool, bool, bool, bool, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)#1}, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, bool, bool, bool, 10ul>(sqlite::database_binder&, Data::SetCalendars()::{lambda(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, bool, bool, bool, bool, bool, bool, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)#1}&, (std::enable_if&&)...)':
/usr/local/include/sqlite_modern_cpp.h:366: undefined reference to `void sqlite::get_col_from_db<bool>(sqlite::database_binder&, int, bool&)'
/tmp/ccqEtE2a.o:/usr/local/include/sqlite_modern_cpp.h:366: more undefined references to `void sqlite::get_col_from_db<bool>(sqlite::database_binder&, int, bool&)' follow

After I delete this line, no error occurs when compiling.
However, the library doesn't work well.
When I'm trying to query some data from the database, it get nothing.
So, what is the function of this line? How can I fix it?

@aminroosta aminroosta reopened this Jul 8, 2016
@aminroosta
Copy link
Collaborator

@semsevens That line gets values returned from database to pass to the lambda function call.
I can't guess any reason why your code fails because all of our tests passes on gcc-6.1.1.

Can you please write a minimal program that fails to compile with the last version of library.
I will add it to to our tests and try to fix the issue ;)

@semsevens
Copy link
Contributor Author

@aminroosta Here is the minimal program:

#include<iostream>
#include <sqlite_modern_cpp.h>
using namespace  sqlite;
using namespace std;

int main() {

    try {
        // creates a database file 'dbfile.db' if it does not exists.
        database db("dbfile.db");

        // executes the query and creates a 'user' table
        db <<
            "create table if not exists user ("
            "   _id integer primary key autoincrement not null,"
            "   age int,"
            "   name text,"
            "   weight real,"
            "   handsome int"
            ");";

        db << "insert into user (age,name,weight,handsome) values (?,?,?,?);"
            << 20
            << u"bob"
            << 83.25
            << true;

        db << "select age,name,weight,handsome from user where age > ? ;"
            << 18
            >> [&](int age, string name, double weight, bool handsome) {
            cout << age << ' ' << name << ' ' << weight << ' ' << handsome << endl;
        };

    }
    catch (exception& e) {
        cout << e.what() << endl;
    }
}

I think I figure out why following errors occurred:

/usr/local/include/sqlite_modern_cpp.h:366: undefined reference to `void sqlite::get_col_from_db<bool>(sqlite::database_binder&, int, bool&)'

It's the Boolean Datatype, as the sqlite's document said:

SQLite does not have a separate Boolean storage class. Instead, Boolean values are stored as integers 0 (false) and 1 (true).

So does the sqlite_modern_cpp.
To support bool argument for lambda function, I add some lines.
Here is my code: bool argument support for lambda function call
So, it's my mistake to passing the bool argument to the lambda function.
To solve my problem, there are two options:

  1. Pass the int argument instead of the bool one.
  2. Add bool argument support to the sqlite_modern_cpp.
    Is it necessary to adding bool argument support?

@aminroosta
Copy link
Collaborator

aminroosta commented Jul 9, 2016

Supporting booleans by converting them to and back from integers makes the library more consistent.
But we must update README to say that booleans are stored as integers(because sqlite has no native boolean data type).

@semsevens Are you interested to send a PR for this? 😉

@semsevens
Copy link
Contributor Author

Yeah, I send a PR. .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants