当我有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)
如果Dims
应该等于传递的参数数,您应该使用sizeof...
操作符,而不是让调用者指定大小。
CTAD(类模板实参推导)仅在类的所有模板实参都推导出来时才有效。
解决方法是让所有参数都被推导出来。您可以将推断索引的类包装成另一个可以显式给出大小的类:
#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');
}
现场演示
为什么以及如何解决这个问题?
当使用类模板实参推导(又名CTAD)时,所有模板形参必须由推导过程或从默认实参中确定。不可能显式指定几个参数并推断其他.
所以解你必须显式地指定所有模板参数,或者让所有参数都被推导出来。解决这个问题的一种方法是:
MIndices<4, char, char, char, char> myI('i', 'j', 'l', 'z');
演示工作
也许有一个更简单的例子可以帮助说明这一点:
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
}
如果这样做不好,请告诉我。
您可以选择使用sizeof...(Indices)
,因此似乎不需要额外的size_t
类型的非类型模板参数。