在 cppreference add_pointer ,据说我们可以将其实现为:
namespace detail {
template <class T>
struct type_identity { using type = T; }; // or use std::type_identity (since C++20)
template <class T>
auto try_add_pointer(int) -> type_identity<typename std::remove_reference<T>::type*>;
template <class T>
auto try_add_pointer(...) -> type_identity<T>;
} // namespace detail
template <class T>
struct add_pointer : decltype(detail::try_add_pointer<T>(0)) {};
我的问题是 try_add_pointer
有什么用?
我知道这是 SFINAE。但为什么实现需要它?
最佳答案
如果您仔细阅读有关 cppreference 的页面,您会注意到这句话
Otherwise (if T is a cv- or ref-qualified function type), provides the member typedef type which is the type T.
函数有自己的类型。通常,你会在正常代码中看到类似 int(int)
的类型。 ,即接受单个整数并返回整数的函数类型。这是参数类型 std::function
期望,例如 std::function<int(int)>
.
然而,函数类型集也包含与成员函数相关的奇怪之处。比如
struct foo {
int bar(int) const;
};
int(int) const
是 bar
的函数类型.虽然此类型存在于类型系统中,但其用途有限。
[dcl.fct]
6 A cv-qualifier-seq or a ref-qualifier shall only be part of:
- the function type for a non-static member function,
- the function type to which a pointer to member refers,
- the top-level function type of a function typedef declaration or alias-declaration,
- the type-id in the default argument of a type-parameter ([temp.param]), or
- the type-id of a template-argument for a type-parameter ([temp.names]).
The effect of a cv-qualifier-seq in a function declarator is not the same as adding cv-qualification on top of the function type. In the latter case, the cv-qualifiers are ignored. [ Note: a function type that has a cv-qualifier-seq is not a cv-qualified type; there are no cv-qualified function types. — end note ] [ Example:
typedef void F(); struct S { const F f; // OK: equivalent to: void f(); };
— end example ] The return type, the parameter-type-list, the ref-qualifier, and the cv-qualifier-seq, but not the default arguments ([dcl.fct.default]) or the exception specification ([except.spec]), are part of the function type.
所以这个特征允许你给它一个函数类型,比如 int() const
, 并且它应该原封不动地返回。
那就是try_add_pointer
因为正如你从上面的列表中看到的那样,没有指向这些函数的常规指针,我们将在 typename std::remove_reference<T>::type*
中得到一个替换失败。 .但感谢 SFINAE,存在后备方案。
关于c++ - std::add_pointer,try_add_pointer 在可能的实现中有什么用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60932682/