首页 > 解决方案 > 如何对使用基类构造函数的派生类进行参数推导?

问题描述

当派生类使用基类构造函数时,演绎似乎总是失败。但是,当基类有很多构造函数时,重新定义所有构造函数是非常笨拙的。当基类使用新的构造函数快速演变时,这也是一种痛苦。老问题是 2 年多前提出的,所以我想知道:在 2020 年 c++17 和 c++2a 可用时,是否有任何解决方法?

template<typename ...As>
class base_t
{
public:
    base_t(As... args){}
};

template<typename ...As>
class A_t: public base_t<As...>
{
public:
    A_t(As... args): base_t<As...>{args...} {};
};

template<typename ...As>
class B_t: public base_t<As...>
{
    using base_t<As...>::base_t;
};

int main()
{
    base_t a{1, 2.0f};
    A_t{1, 2.0f};
    B_t{1, 2.0f}; //fails unless explicitly specialize the template
    return 0;
}

根据@Sam 和@Barry 更新:

扣分指南很有帮助。但是,对于更复杂一点的情况,它仍然失控:

template <typename A>
struct D_t {
    A x;
    D_t(A x) :x{x} {}
};
template<typename A, typename B>
class base2_t
{
public:
    base2_t(A a, B b){std::cout << "1\n";}
    base2_t(A a, D_t<B> c, int x){std::cout << "2\n";}
    base2_t(A a, B b, int x){std::cout << "3\n";}
    base2_t(A a, B b, int x, float y){std::cout << "4\n";}
    explicit base2_t(A(*fp)(B)){std::cout << "5\n";}
    // if we have lots of similar things like above
    // we will quickly end up write lots of different
    // guides.
};
template<typename A, typename B>
class C_t: public base2_t<A, B>
{
    using base2_t<A, B>::base2_t;
};
template<typename A, typename B, typename ...As>
C_t(A, B, As...)->C_t<A, B>;
template<typename A, typename B>
C_t(A(*)(B))->C_t<A, B>;
float func1(int x)
{
    return x;
}
int main()
{
    C_t{1, 2.0f, 3};
    base2_t{1, D_t{2.0f}, 3};
    C_t{1, D_t{2.0f}, 3}; // this is wrong, we have to deal with it by checking types and write different guides.
    base2_t{&func1};
    C_t{&func1};
}

标签: c++c++17c++20

解决方案


为 c++20提出了能够从基类继承推导指南。然而,这个功能并没有进入,正如最后一行所说:

继承构造函数的 CTAD 措辞并未及时在 C++20 委员会草案中最终确定,并将在稍后的时间点在单独的措辞文件中发布。

因此,到目前为止,您需要明确地为派生类提供推导指南(或像为 所做的那样定义构造函数A_t)。希望这将在 c++23 中得到修复。


推荐阅读