【发布时间】:2022-01-12 12:19:04
【问题描述】:
我有一个模板类,但只能从构造函数中推导出部分模板参数。
有没有办法在调用构造函数时在尖括号内提供其余的模板参数?
假设我们使用的是 C++17。
template<typename T1, typename T2>
struct S
{
T2 t2;
S(const T2& _t2) : t2{_t2} {}
void operator()(const T1& t1)
{
std::cout << t1 << ", " << t2 << '\n';
}
};
int main()
{
S<int, double> s {3.14};
std::function<void(int)> func = s;
func(42);
// What I want:
//S<int> s2 {3.14}; <- T1 is provided in the angle brackets, T2 is deduced
//std::function<void(int)> func2 = s;
//func2(42);
}
据我所知,我们需要在尖括号中提供所有模板参数,或者不提供任何参数并使用 CTAD。 问题是我不想编写所有模板参数(在我的实际用例中,它们中有 5-6 个,它们非常冗长)但我也不想在构造函数中传递所有参数,因为其中一些不用于构造对象。对于 operator() 方法,我只需要它们的类型。
我无法将 operator() 方法模板化,因为我想将它绑定到 std::function 对象,并且我无法在绑定期间推断模板参数类型。所以这就是为什么我需要包装类中的所有类型。
这种部分模板推导存在于函数中。
例如:
template<typename T1, typename T2>
void foo(const T2& t2)
{
T1 t1{};
std::cout << t1 << ", " << t2 << '\n';
}
int main()
{
foo<int>(3.4); //T1 is explicitly int, T2 is deduced to be double
}
我目前的解决方案是利用这个特性,通过函数构造对象:
template<typename U1, typename U2>
S<U1, U2> construct_S(const U2& t2)
{
return S<U1, U2>{t2};
}
int main()
{
auto s2 = construct_S<int>(1.5);
std::function<void(int)> func2 = s2;
func2(23);
}
我觉得这个解决方案很笨拙,因为我们使用外部函数来构造对象。
我想知道是否有更清洁的解决方案。
也许有一些扣除指南?我不确定。
【问题讨论】:
-
您也可以将模板一分为二,将一个嵌套在另一个中,并使用 CTAD 作为内部的:
auto s = S<Foo>::impl(42); -
make_XXX是 CTAD 之前的方式,允许“部分”扣除。 -
这个答案确实适用于stackoverflow.com/a/57563652/4117728。这个答案stackoverflow.com/a/57563907/4117728 显示了如何使用类似于您的方法的
make_...。它不是您想听到的答案,但这并不能减少重复