Search code examples
c++c++20template-argument-deductionclass-template

C++ - Deducing type from inherited constructor's arguments for class template


I have a class template that inherits the constructors of the base class template. (As for c++20) Is there a way to deduce the template arguments of the derived class from the constructor arguments of base?

If I specify the type explicitly, that works. Or if I reimplement the constructor and call the constructor of base, that also would work but is there a way to do without that?

template<typename T>
struct CTestBase
{
    using Type = T;

    CTestBase() = default;
    CTestBase(T t){}
};

template<typename T>
struct CTestDer : public CTestBase<T>
{
    using CTestBase<T>::CTestBase;
};

void test()
{
    //CTestDer der(int{}); //ERROR
    CTestDer<int> der(int{}); //OK
}

Solution

  • You can add a user-defined deduction guide:

    #include <utility>
    
    template<typename T>
    struct CTestBase
    {
        using Type = T;
    
        CTestBase() = default;
        CTestBase(T t){}
    };
    
    template<typename T>
    struct CTestDer : public CTestBase<T>
    {
        using CTestBase<T>::CTestBase;
    };
    
    template<typename T>
    CTestDer(T &&t) -> CTestDer<std::remove_cvref_t<T>>;
    
    void test()
    {
        CTestDer der(int{}); // OK now.
    }
    

    With a little bit more work it should be possible to:

    1. Use a variadic template in the deduction guide
    2. Have the deduction guide use decltype to construct, using its own deduction guide, the superclass
    3. Use a specialization to figure out the superclass's template parameters
    4. Use that to construct the subclass, to deduce it

    This should handle anything. But this will be a lot of work. For this simple use case, and if it's not expected that the superclass will change much, this would be overkill.