C++20 概念是否支持将模板函数修复为模板参数问题?
Do C++20 concepts enable fixing template function as template argument problem?
如果你在 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 语句,它表示如果仿函数参数是模板,那么该仿函数的模板参数必须匹配容器 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
命名一个模板函数。具有不完整模板参数列表的模板函数名称在重载解析期间被转换为函数。重载解析需要将函数名转换为指向固定签名的指针,或者使用 ()
s.
调用
概念没用。
现在你可以使用旧技巧了;有一个函数重载,它在非推导上下文中接受一个函数指针。当我编写类似 std 函数的类型时,正是出于这个原因,我添加了 R(*)(Args...)
重载;当存在类型完全匹配的重载时允许重载解析。
但这不是基于概念的。
如果你在 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 语句,它表示如果仿函数参数是模板,那么该仿函数的模板参数必须匹配容器 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
命名一个模板函数。具有不完整模板参数列表的模板函数名称在重载解析期间被转换为函数。重载解析需要将函数名转换为指向固定签名的指针,或者使用 ()
s.
概念没用。
现在你可以使用旧技巧了;有一个函数重载,它在非推导上下文中接受一个函数指针。当我编写类似 std 函数的类型时,正是出于这个原因,我添加了 R(*)(Args...)
重载;当存在类型完全匹配的重载时允许重载解析。
但这不是基于概念的。