fnc12/sqlite_orm

Cannot convert condition to tuple in `mapped_view`

Opened this issue · 2 comments

This is a regression since v1.9.
When using iterate (or more generally, mapped_view) with where() (or more generally, a condition), I get an error:

sqlite_orm.h:15971:75: error: no viable conversion from 'sqlite_orm::internal::where_t<sqlite_orm::internal::is_equal_t<std::basic_string<char> MyRecord::*, std::basic_string<char>>>' to 'conditions_type' (aka 'tuple<sqlite_orm::internal::where_t<sqlite_orm::internal::is_equal_t<std::basic_string<char, std::char_traits<char>, std::allocator<char>> MyRecord::*, std::basic_string<char, std::char_traits<char>, std::allocator<char>>>>, sqlite_orm::internal::order_by_t<long MyRecord::*>>')
 15971 |                 storage(storage), connection(std::move(conn)), expression{std::forward<Args>(args)...} {}
       |                                                                           ^~~~~~~~~~~~~~~~~~~~~~~~
sqlite_orm.h:22161:24: note: in instantiation of member function 'sqlite_orm::internal::mapped_view<MyRecord, sqlite_orm::internal::storage_t<...>, sqlite_orm::internal::where_t<sqlite_orm::internal::is_equal_t<std::basic_string<char> MyRecord::*, std::basic_string<char>>>, sqlite_orm::internal::order_by_t<long MyRecord::*>>::mapped_view' requested here
 22161 |                 return {*this, std::move(con), std::forward<Args>(args)...};
       |                        ^
MyStorage.cpp:377:35: note: in instantiation of function template specialization 'sqlite_orm::internal::storage_t<...>::iterate<MyRecord, MyRecord, sqlite_orm::internal::where_t<sqlite_orm::internal::is_equal_t<std::basic_string<char> MyRecord::*, std::basic_string<char>>>, sqlite_orm::internal::order_by_t<long MyRecord::*>>' requested here
  377 |   for (auto& record : mStorage->m.iterate<MyRecord>(
      |                                   ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/tuple:1356:17: note: candidate constructor not viable: no known conversion from 'sqlite_orm::internal::where_t<sqlite_orm::internal::is_equal_t<std::basic_string<char> MyRecord::*, std::basic_string<char>>>' to 'const tuple<where_t<is_equal_t<basic_string<char> MyRecord::*, basic_string<char>>>, order_by_t<long MyRecord::*>> &' for 1st argument
 1356 |       constexpr tuple(const tuple&) = default;
      |                 ^     ~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/tuple:1358:17: note: candidate constructor not viable: no known conversion from 'sqlite_orm::internal::where_t<sqlite_orm::internal::is_equal_t<std::basic_string<char> MyRecord::*, std::basic_string<char>>>' to 'tuple<where_t<is_equal_t<basic_string<char> MyRecord::*, basic_string<char>>>, order_by_t<long MyRecord::*>> &&' for 1st argument
 1358 |       constexpr tuple(tuple&&) = default;
      |                 ^     ~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/tuple:1363:2: note: candidate template ignored: could not match 'tuple' against 'where_t'
 1363 |         tuple(const tuple<_U1, _U2>& __in)
      |         ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/tuple:1377:2: note: candidate template ignored: could not match 'tuple' against 'where_t'
 1377 |         tuple(tuple<_U1, _U2>&& __in)
      |         ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/tuple:1409:2: note: candidate template ignored: could not match 'pair' against 'where_t'
 1409 |         tuple(const pair<_U1, _U2>& __in)
      |         ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/tuple:1423:2: note: candidate template ignored: could not match 'pair' against 'where_t'
 1423 |         tuple(pair<_U1, _U2>&& __in)
      |         ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/tuple:1370:2: note: explicit constructor is not a candidate
 1370 |         tuple(const tuple<_U1, _U2>& __in)
      |         ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/tuple:1384:2: note: explicit constructor is not a candidate
 1384 |         tuple(tuple<_U1, _U2>&& __in)
      |         ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/tuple:1416:2: note: explicit constructor is not a candidate
 1416 |         tuple(const pair<_U1, _U2>& __in)
      |         ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/tuple:1431:2: note: explicit constructor is not a candidate
 1431 |         tuple(pair<_U1, _U2>&& __in)
      |         ^

This is caused by the constructor of mapped_view constructing expression as expression{std::forward<Args>(args)...}, while it should be expression{{std::forward<Args>(args)...}} (construct a struct with a tuple inside).

I can reproduce this with clang 20.0.0, clang 14.0.0, Apple clang 15.0.0, MSVC 19.39.33523, all with C++20.

@stevenwdv could you please show the least code which can repro this issue? It will help a lot in creating a unit test which covers this issue to avoid it firing in future again

Hi! Apparently the issue occurs when using iterate with where + order_by, not with only one:

#include <iostream>
#include <string>

#include <sqlite_orm.h>  // v1.9

struct Person {
    std::string name;
    bool dead{};
};

void listPeople(const std::string &path) {
    using namespace sqlite_orm;

    auto storage = make_storage(path,
        make_table("People",
            make_column("name", &Person::name)
        )
    );
    for (const auto &person : storage.iterate<Person>(
        where(c(&Person::dead) == false),
        order_by(&Person::name).asc()
    )) {
        std::cout << person.name << '\n';
    }
}

Working demo on Compiler Explorer