如何使用 `requires` 和 `-> return_type` 声明成员函数
How to Declar Member Function with both `requires` and `-> return_type`
我想写一个class模板,其中:
A<float>
只有一个成员变量val
;
A<int>
有一个成员变量val
和一个成员函数make_unsigned
(returnunsigned
).
我想明确说明 make_unsigned
的 return 值。这是我的代码。
#include <concepts>
template<typename T> struct A
{
T val;
std::make_unsigned_t<T> make_unsigned() requires std::signed_integral<T>
{
return static_cast<std::make_unsigned<T>::type>(val);
}
};
int main()
{
A<float> val;
return 0;
}
我也试过auto make_unsigned() requires std::signed_integral<T> -> std::make_unsigned_t<T>
和auto make_unsigned() -> std::make_unsigned_t<T> requires std::signed_integral<T>
,但是都编译不出来。它抱怨:
~ LANG=C g++ main.cpp -std=c++20 -o main
In file included from /usr/include/c++/10.2.0/bits/move.h:57,
from /usr/include/c++/10.2.0/bits/stl_pair.h:59,
from /usr/include/c++/10.2.0/utility:70,
from /usr/include/c++/10.2.0/array:38,
from main.cpp:1:
/usr/include/c++/10.2.0/type_traits: In instantiation of ‘struct std::make_unsigned<float>’:
/usr/include/c++/10.2.0/type_traits:1965:11: required by substitution of ‘template<class _Tp> using make_unsigned_t = typename std::make_unsigned::type [with _Tp = float]’
main.cpp:8:29: required from ‘struct A<float>’
main.cpp:17:14: required from here
/usr/include/c++/10.2.0/type_traits:1826:62: error: invalid use of incomplete type ‘class std::__make_unsigned_selector<float, false, false>’
1826 | { typedef typename __make_unsigned_selector<_Tp>::__type type; };
| ^~~~
/usr/include/c++/10.2.0/type_traits:1733:11: note: declaration of ‘class std::__make_unsigned_selector<float, false, false>’
1733 | class __make_unsigned_selector;
或:
~ LANG=C g++ main.cpp -std=c++20 -o main
main.cpp:8:59: error: base operand of ‘->’ is not a pointer
8 | auto make_unsigned() requires std::signed_integral<T> -> std::make_unsigned_t<T>
| ^~
main.cpp:8:62: error: invalid use of ‘using make_unsigned_t = typename std::make_unsigned<_Tp>::type’
8 | auto make_unsigned() requires std::signed_integral<T> -> std::make_unsigned_t<T>
| ^~~
cc1plus: error: expression must be enclosed in parenthese
或:
~ LANG=C g++ main.cpp -std=c++20 -o main
In file included from /usr/include/c++/10.2.0/bits/move.h:57,
from /usr/include/c++/10.2.0/bits/stl_pair.h:59,
from /usr/include/c++/10.2.0/utility:70,
from /usr/include/c++/10.2.0/array:38,
from main.cpp:1:
/usr/include/c++/10.2.0/type_traits: In instantiation of ‘struct std::make_unsigned<float>’:
/usr/include/c++/10.2.0/type_traits:1965:11: required by substitution of ‘template<class _Tp> using make_unsigned_t = typename std::make_unsigned::type [with _Tp = float]’
main.cpp:8:10: required from ‘struct A<float>’
main.cpp:17:14: required from here
/usr/include/c++/10.2.0/type_traits:1826:62: error: invalid use of incomplete type ‘class std::__make_unsigned_selector<float, false, false>’
1826 | { typedef typename __make_unsigned_selector<_Tp>::__type type; };
| ^~~~
/usr/include/c++/10.2.0/type_traits:1733:11: note: declaration of ‘class std::__make_unsigned_selector<float, false, false>’
1733 | class __make_unsigned_selector;
我该怎么做?
std::make_unsigned
对 SFINAE 不友好,所以你必须
不要在 return 类型上显式,使用 auto
/decltype(auto)
:
auto make_unsigned() requires std::signed_integral<T>
{
return static_cast<std::make_unsigned<T>::type>(val);
}
添加一个“友好的”特征(一个不会使程序格式错误的特征,并且类型无效),另外使用 return 类型(因为函数不是模板, 这里没有 SFINAE):
template <typename T>
struct make_unsigned_or_self
{
using type = T;
};
template <typename T>
using make_unsigned_or_self_t = typename make_unsigned_or_self<T>::type;
template <std::signed_integral T>
struct make_unsigned_or_self<T>
{
using type = std::make_unsigned_t<T>;
};
然后
make_unsigned_or_self_t<T> make_unsigned() requires std::signed_integral<T>
{
return static_cast<std::make_unsigned<T>::type>(val);
}
我想写一个class模板,其中:
A<float>
只有一个成员变量val
;A<int>
有一个成员变量val
和一个成员函数make_unsigned
(returnunsigned
).
我想明确说明 make_unsigned
的 return 值。这是我的代码。
#include <concepts>
template<typename T> struct A
{
T val;
std::make_unsigned_t<T> make_unsigned() requires std::signed_integral<T>
{
return static_cast<std::make_unsigned<T>::type>(val);
}
};
int main()
{
A<float> val;
return 0;
}
我也试过auto make_unsigned() requires std::signed_integral<T> -> std::make_unsigned_t<T>
和auto make_unsigned() -> std::make_unsigned_t<T> requires std::signed_integral<T>
,但是都编译不出来。它抱怨:
~ LANG=C g++ main.cpp -std=c++20 -o main
In file included from /usr/include/c++/10.2.0/bits/move.h:57,
from /usr/include/c++/10.2.0/bits/stl_pair.h:59,
from /usr/include/c++/10.2.0/utility:70,
from /usr/include/c++/10.2.0/array:38,
from main.cpp:1:
/usr/include/c++/10.2.0/type_traits: In instantiation of ‘struct std::make_unsigned<float>’:
/usr/include/c++/10.2.0/type_traits:1965:11: required by substitution of ‘template<class _Tp> using make_unsigned_t = typename std::make_unsigned::type [with _Tp = float]’
main.cpp:8:29: required from ‘struct A<float>’
main.cpp:17:14: required from here
/usr/include/c++/10.2.0/type_traits:1826:62: error: invalid use of incomplete type ‘class std::__make_unsigned_selector<float, false, false>’
1826 | { typedef typename __make_unsigned_selector<_Tp>::__type type; };
| ^~~~
/usr/include/c++/10.2.0/type_traits:1733:11: note: declaration of ‘class std::__make_unsigned_selector<float, false, false>’
1733 | class __make_unsigned_selector;
或:
~ LANG=C g++ main.cpp -std=c++20 -o main
main.cpp:8:59: error: base operand of ‘->’ is not a pointer
8 | auto make_unsigned() requires std::signed_integral<T> -> std::make_unsigned_t<T>
| ^~
main.cpp:8:62: error: invalid use of ‘using make_unsigned_t = typename std::make_unsigned<_Tp>::type’
8 | auto make_unsigned() requires std::signed_integral<T> -> std::make_unsigned_t<T>
| ^~~
cc1plus: error: expression must be enclosed in parenthese
或:
~ LANG=C g++ main.cpp -std=c++20 -o main
In file included from /usr/include/c++/10.2.0/bits/move.h:57,
from /usr/include/c++/10.2.0/bits/stl_pair.h:59,
from /usr/include/c++/10.2.0/utility:70,
from /usr/include/c++/10.2.0/array:38,
from main.cpp:1:
/usr/include/c++/10.2.0/type_traits: In instantiation of ‘struct std::make_unsigned<float>’:
/usr/include/c++/10.2.0/type_traits:1965:11: required by substitution of ‘template<class _Tp> using make_unsigned_t = typename std::make_unsigned::type [with _Tp = float]’
main.cpp:8:10: required from ‘struct A<float>’
main.cpp:17:14: required from here
/usr/include/c++/10.2.0/type_traits:1826:62: error: invalid use of incomplete type ‘class std::__make_unsigned_selector<float, false, false>’
1826 | { typedef typename __make_unsigned_selector<_Tp>::__type type; };
| ^~~~
/usr/include/c++/10.2.0/type_traits:1733:11: note: declaration of ‘class std::__make_unsigned_selector<float, false, false>’
1733 | class __make_unsigned_selector;
我该怎么做?
std::make_unsigned
对 SFINAE 不友好,所以你必须
不要在 return 类型上显式,使用
auto
/decltype(auto)
:auto make_unsigned() requires std::signed_integral<T> { return static_cast<std::make_unsigned<T>::type>(val); }
添加一个“友好的”特征(一个不会使程序格式错误的特征,并且类型无效),另外使用 return 类型(因为函数不是模板, 这里没有 SFINAE):
template <typename T> struct make_unsigned_or_self { using type = T; }; template <typename T> using make_unsigned_or_self_t = typename make_unsigned_or_self<T>::type; template <std::signed_integral T> struct make_unsigned_or_self<T> { using type = std::make_unsigned_t<T>; };
然后
make_unsigned_or_self_t<T> make_unsigned() requires std::signed_integral<T> { return static_cast<std::make_unsigned<T>::type>(val); }