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

Can't construct tuple<T, U> passing (const T&, const U&) in the constructor #28

Open
YarikTH opened this issue Jan 7, 2023 · 2 comments

Comments

@YarikTH
Copy link

YarikTH commented Jan 7, 2023

I tried to use tuplet::tuple as a optional drop-in replacement for std::tuple to check if it reduces compilation times for my use case. But compilation failed. I reproduced it on godbolt.

Any ideas? Is it principal limitation of tuplet so, some wrapper function should be called or it is a bug that can be easily fixed?

#include <memory>

#ifdef USE_STD_TUPLE
#include <tuple>

using std::apply;
using std::tie;
using std::tuple;
#else
#include "https://raw.githubusercontent.com/codeinred/tuplet/main/include/tuplet/tuple.hpp"

using tuplet::apply;
using tuplet::tie;
using tuplet::tuple;
#endif

template <typename... DepValues>
class Foo {
   public:
    Foo(const std::shared_ptr<DepValues>&... deps) : m_deps(deps...) {}

   private:
    using dep_holder_t = tuple<std::shared_ptr<DepValues>...>;

    dep_holder_t m_deps;
};

int main() {
    using T = Foo<int, int>;

    T t{std::make_shared<int>(3), std::make_shared<int>(5)};
}
@YarikTH
Copy link
Author

YarikTH commented Jan 8, 2023

Further investigation have shown that while std::tuples are constructed from multiple arguments without problem m_deps(deps...), tuplet::tuple requires wrapping args in curly brackets m_deps({deps...}). It seems that std::tuple works with curly brackets too, so they can be used for both.

Modified example: https://godbolt.org/z/sdsPevGaq
I simplified types from std::shared_ptr<T> to just T and add dumping, so we can see that result is expected.

#include <iostream>

#ifdef USE_STD_TUPLE
#include <tuple>

using std::apply;
using std::tie;
using std::tuple;
#define WRAP_TUPLE_ARGS(...) __VA_ARGS__
#else
#include "https://raw.githubusercontent.com/codeinred/tuplet/main/include/tuplet/tuple.hpp"

using tuplet::apply;
using tuplet::tie;
using tuplet::tuple;
#define WRAP_TUPLE_ARGS(...) { __VA_ARGS__ }
#endif

template <typename... DepValues>
class Foo {
   public:
    Foo(const DepValues&... deps) : m_deps(WRAP_TUPLE_ARGS(deps...)) {}

    void dump() { apply(Foo::dumpValues<DepValues...>, this->m_deps); }

   private:
    template <typename... Values>
    static void dumpValues(const Values&... values) {
        (Foo::dumpOne(values), ...);
    };

    template <class Value>
    static void dumpOne(const Value& value) {
        std::cout << value << ", ";
    }

    using dep_holder_t = tuple<DepValues...>;

    dep_holder_t m_deps;
};

int main() {
    using T = Foo<int, int>;

    T t{3, 5};

    t.dump();
}

@YarikTH
Copy link
Author

YarikTH commented Jan 8, 2023

clang-12 warns on braces https://godbolt.org/z/rYTTPxcTT

suggest braces around initialization of subobject [-Wmissing-braces]

and I have no idea how to change code to satisfy it.

Also I found another difference: If we have tuple of template wrappers that accept single argument, then std::tuple can automatically construct it, while tuplet can't. It hard to explain, just look at m_stots in example.

https://godbolt.org/z/YT8bPsW9W

#include <iostream>

#ifdef USE_STD_TUPLE
#include <tuple>

using std::apply;
using std::tie;
using std::tuple;
#define WRAP_TUPLE_ARGS(...) __VA_ARGS__
#else
#include "https://raw.githubusercontent.com/codeinred/tuplet/main/include/tuplet/tuple.hpp"

using tuplet::apply;
using tuplet::tie;
using tuplet::tuple;
#define WRAP_TUPLE_ARGS(...) { __VA_ARGS__ }
#endif

template <typename... DepValues>
class Foo {
   public:
    Foo(const DepValues&... deps)
        : m_deps(WRAP_TUPLE_ARGS(deps...))
        , m_slots(WRAP_TUPLE_ARGS(deps...))
    {}

    void dump() { apply(Foo::dumpValues<DepValues...>, this->m_deps); }

   private:
    template <typename... Values>
    static void dumpValues(const Values&... values) {
        (Foo::dumpOne(values), ...);
    };

    template <class Value>
    static void dumpOne(const Value& value) {
        std::cout << value << ", ";
    }

    template <typename T>
    struct slot
    {
        explicit slot( const T& source )
        {}
    };

    using dep_holder_t = tuple<DepValues...>;

    dep_holder_t m_deps;

    tuple<slot<DepValues>...> m_slots;
};

int main() {
    using T = Foo<int, int>;

    T t{3, 5};

    t.dump();
}

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

1 participant