C++17 中的部分 class 模板参数推导

Partial class template argument deduction in C++17

在下面的示例中,我们使用 C++17 功能 "Class template argument deduction" 来推断 val 的类型为 Base<int, double, bool>:

template<class T, class U, class V>
struct Base {
    Base(T, U) { };
    Base(T, U, V) { };
    Base(V) { };
};

void func() {
    Base val(1, 4., false);
}

现在,是否可以部分指定模板参数,并让其余的推导?实际上这样的东西:

Base<V = bool> val1(1, 4.);        // U & V deduced --> Base<int, double, bool>
Base<T = bool, T = int> val2(5.);  // V deduced     --> Base<bool, int, double>

我试过了,例如

template<class T, class U> using Base2 = Base<T, U, double>;

void func() {
    NewBase2 val(1, 2);
}

但无法编译:'Base2': use of alias template requires template argument list.

是否可以通过某种方式进行部分扣除?如果直接不行,有什么好的解决方法吗?

CTAD(Class 模板参数推导)目前是一个全有或全无的过程。您要么不指定任何内容并允许编译器推导所有参数,要么指定所有参数使编译器退出循环。

有一篇论文(P1021R0) which asks for this and more, but it has not yet been accepted. There was a paper asking for partial specialization but after revisions it has been removed. The newest revision还包括提议在使用别名时具有CTAD功能


Per @Barry Support for Alias templates (P1814) and Aggregates (P1816) 已添加到 C++20 的工作草案中。未添加对部分 CTAD 或具有继承构造函数的 CTAD 的支持。

您可以添加推导指南如下:

template<class T, class U, class V>
Base(T, U) -> Base<T, U, bool>;

template<class V>
Base(V) -> Base<bool, int, V>;

允许

Base val1(1, 4.); // Base<int, double, bool>
Base val2(5.);    // Base<bool, int, double>

如果您想指定 "default" 模板,您可以使用 make_

的旧方法
template <typename V, typename T, typename U>
Base<T, U, V> make_Base(T t, U u)
{
    return Base<T, U, V>{t, u};
}

template <typename T, typename U, typename V>
Base<T, U, V> make_Base(V v)
{
    return Base<T, U, V>{v};
}


auto val1 = make_Base<bool>(1, 4.);   // Base<int, double, bool>
auto val2 = make_Base<bool, int>(5.); // Base<bool, int, double>