【发布时间】:2021-03-31 19:38:38
【问题描述】:
如果你在 C++20 中尝试一些相对简单的东西,它会以 unhelpful error message spam 内爆。
int main() {
auto as = std::vector{1,3,24,};
auto bs = std::vector{1,4,10};
auto cs = std::vector<float>{};
std::ranges::transform(as, bs, std::back_inserter(cs), std::max);
std::ranges::copy(cs, std::ostream_iterator<float>(std::cout, " "));
}
原因是std::max 是模板函数,所以它不起作用。
这可以通过将参数设为 lambda 或制作一个小型辅助函子来轻松解决。
但我想知道是否可以使用 C++ 概念来告诉我们想要什么模板实例化?
例如,我们修改了一些 requires 语句,如果 functor 参数是模板,那么该 functor 的模板参数必须与容器 value_type 匹配。
我怀疑这是可能的,因为我认为在模板重载解析和约束检查开始之前必须知道函子的确切类型,换句话说,没有从概念到调用站点的信息“反向传播”。
但我不确定所以我决定问一下。
如果你想知道我尝试了什么,这里是我的代码,但它很破碎,我无法编写模板模板参数代码......
但无论如何我希望它能说明这个想法......
template<typename C, typename F>
struct xtransform
{
xtransform(C& c, F f) : c_(c), f_(f){}
void operator()(){
}
C c_;
F f_;
};
template<typename C, template<typename> typename F, typename FArg>
requires requires {
std::is_same_v<typename C::value_type, FArg>;
}
struct xtransform<C, F<FArg>>
{
xtransform(C& c, F<FArg> f) : c_(c), f_(f){}
void operator()(C& c, F<FArg> f){
}
C c_;
F<FArg> f_;
};
【问题讨论】:
-
我怀疑这是可能的,因为我认为在模板重载决议和约束检查开始之前必须知道函子的确切类型正确。名称
std::max命名一个模板。你不能从中得到具体的东西。我认为如果添加了采用模板模板参数的重载,则可以修复它。 -
@NathanOliver 你最后一句话是在谈论语言更改或我的代码更改吗?因为那是我认为我试图做的。
-
不是语言变化,而是标准库变化。至少我认为它可以通过更改库来修复。我有一些疑问,因为我仍然认为您需要将具体对象传递给函数。
-
@NathanOliver:模板模板参数必须是类/别名模板;函数模板只是在(他们自己的!)重载决议期间之外的东西。
-
@NathanOliver 我认为最简单的库更改是使
std::max成为 neibloid,尽管这会破坏现有代码。
标签: c++ c++20 c++-concepts template-templates