具有两个模板参数的可变参数模板推导失败

variadic template deduction with two template argument fails

当我有 class:

template <std::same_as<char> ... Indices>
struct MIndices {
        std::tuple<Indices...> indices;
        MIndices() = delete;
        constexpr explicit MIndices(Indices... args) : indices(args...) {
        }
};

以下调用有效:

    MIndices myI('i', 'j', 'l', 'z');

但将模板更改为以下内容:

template <size_t Dims, std::same_as<char> ... Indices>
struct MIndices {
        std::tuple<Indices...> indices;
        MIndices() = delete;
        constexpr explicit MIndices(Indices... args) : indices(args...) {
        }
};

然后用

调用它
    MIndices<4> myI('i', 'j', 'l', 'z');

突然推论失败

为什么以及如何解决这个问题?

所以原则上我只想有一个编译时的方式来指定 元组参数的数量。如果这样做不好,请告诉我。

我正在使用 c++20。 (gcc-12.1)

Why and how can I fix this?

问题是当使用class模板参数推导(aka CTAD)时,所有模板参数必须由推导过程或默认参数确定。 无法明确指定一些参数并推断出其他参数

因此,要解决这个问题,您必须显式指定所有模板参数或推导所有模板参数。所以解决这个问题的一种方法是:

MIndices<4, char, char, char, char> myI('i', 'j', 'l', 'z');

Working demo


也许更简化的示例可能有助于说明这一点:

template<typename T1, typename T2, typename T3>
class Custom
{
    public:
    
        Custom (T1 x, T2 y, T3 z)
        {

        }
};
int main()
{
    std::string s;
    Custom c(3, 2.343, s); //works 

    //Custom<int> b(4, 2,343, s); //WON'T WORK

    Custom<int, int, std::string> k(4, 4, "s"); //works
}

If this is a bad way for doing it please tell me.

您可以选择使用 sizeof...(Indices),因此似乎不需要 size_t.

类型的额外非类型模板参数

如果 Dims 应该等于传递的参数数量,您应该使用 sizeof... 运算符而不是让调用者指定大小。


CTAD(class 模板参数推导)仅在推导 class 的所有模板参数时有效。

解决方法是推导所有参数。您可以将推导索引的 class 包装到另一个可以明确指定大小的索引中:

#include <iostream>
#include <tuple>

template <size_t Dims>
struct wrapper {
    template <std::same_as<char> ... Indices>
    struct MIndices {
        std::tuple<Indices...> indices;
        MIndices() = delete;
        constexpr explicit MIndices(Indices... args) : indices(args...) {
        }
    };
};
    
int main() {
   wrapper<4>::MIndices myI('i', 'j', 'l', 'z');
}

Live Demo