Search code examples
c++c++17stdtuplectad

Inherit CTAD constructor


I have derived from std::tuple and but was unable construct the derived class from an initializer list due to issues with class template argument deduction. Is there a better way to construct such a class beyond just giving it an already constructed tuple first{ std::tuple{1, 1.0f, 1u} };.

template <typename T, typename... Types>
struct first : public std::tuple<T, Types...>
{
    //using std::tuple<T, Types...>::tuple;
    template<typename F>
        requires std::invocable<F, T>
    auto transform(F f)
    {
        auto result = *this;
        std::get<0>(result) = f(std::get<0>(result));
        return result;
    }
};

int main()
{
    //auto tuple = first{ 1, 1.0f, 1u };
    auto tuple = first{ std::tuple{1, 1.0f, 1u} };
    auto tuple2 = tuple.transform([](auto a) {return a + 3; });
}

Solution

  • Inherited constructors are not part of CTAD.

    You might replicate std::tuple's CTAD:

    template <typename T, typename... Types>
    first(T, Types...) -> first<T, Types...>;
    
    // auto tuple = first{1, 1.0f, 1u}; // is ok now
    // auto tuple = first{ std::tuple{1, 1.0f, 1u} }; // broken now
    

    Demo