C ++ 20概念要求存在精确的函数签名 [英] C++20 concept which requires the existence of an exact function signature

查看:68
本文介绍了C ++ 20概念要求存在精确的函数签名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下示例来计算两个值之间的绝对差.

Consider the following example for the calculation of the absolute difference between two values.

template<class T>
auto abs_diff(const T _a, const T _b) {
    return (_a > _b) ? (_a - _b) : (_b - _a);
}

对于某些内置类型, std :: abs 提供了卓越的性能,因此如果 std :: abs(T x)存在,我想使用它(假设对于整数,我们对不同的下溢/上溢行为不感兴趣).为此,我尝试添加以下受约束的模板函数

For some build-in types std::abs provides superior performance, so if std::abs(T x) exists I want to use it (let's assume we are not interested in the different under-/overflow behavior in case of integers). To this end I tried to add the following constrained template function

template<class T> requires requires (T x) { std::abs(x); }
auto abs_diff(const T _a, const T _b) {
    return std::abs(_a - _b);
}

现在,所有存在 std :: abs 的类型都将使用此专用版本.但是,所有可隐式转换为此类类型的类型都将使用它,这是不希望的.所以我的问题是:有没有一种方法要求在概念中存在具有精确签名的函数(即存在 std :: abs(T x),而不仅是存在 std :: abs(T x)> std :: abs(x)进行编译.)

Now all types for which std::abs exists will use this specialized version. However also all types which are implicitly convertible to such a type will use it, which is undesirable. So my question is: is there a way to require the existence of a function with exact signature in a concept (i.e. the existence of std::abs(T x) and not only the fact that std::abs(x) compiles).

注意:上面的示例主要用于说明,并且至少对于我的应用程序可以通过使用 requires(T x){{std :: abs(x)}->std :: same_as< T> ;;} .但是,我对这种问题的一般解决方案感兴趣.

Note: The above example is mostly for illustration and could, at least for my application, be fixed by constraining the return type using requires (T x) { { std::abs(x) } -> std::same_as<T>; }. However I am interested in a general solution for this kind of problem.

推荐答案

我们可以改为测试重载的函数地址表达式& std :: abs 是否可以转换为具有所需功能的指针签名.或者我们可以,除了C ++ 20不允许形成指向大多数标准库函数的指针.

We can test instead if the overloaded function address expression &std::abs can convert to a pointer to function with the desired signature. Or we could, except that C++20 doesn't allow forming pointers to most standard library functions.

在此处保留原始答案以获取信息.对于标准库中没有的重载函数名称,这将是有效的模式.而且无论如何它通常都能正常工作,但是我们不应该依靠它来继续使用较新的库版本.

Leaving this original answer here for information. It would be a valid pattern for an overloaded function name which is not in the standard library. And it often works anyway, but we shouldn't count on that to continue with newer library versions.

#include <cmath>

template<class T>
auto abs_diff(const T _a, const T _b) {
    return (_a > _b) ? (_a - _b) : (_b - _a);
}

template<class T> requires requires (T (*fp)(T)) { fp = &std::abs; }
auto abs_diff(const T _a, const T _b) {
    return std::abs(_a - _b);
}

请参见在Godbolt上进行的测试.

在包含匹配函数模板的名称上使用此技术时,如果没有非模板函数完全匹配,则也可以满足约束条件,但是一个最专业的函数模板可以推导其参数,以便一个专业就是 T(T).

When this technique is used on a name that includes matching function templates, the constraint can also be satisfied if no non-template function is an exact match, but one most-specialized function template can deduce its arguments so that the type of a specialization is exactly T(T).

(在< complex> 中声明了一个 std :: abs 函数模板,但它永远无法与 T(T)类型完全匹配.)

(There is a std::abs function template declared in <complex>, but it can never exactly match type T(T).)

这篇关于C ++ 20概念要求存在精确的函数签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆