C++ 使用SFINAE测试指针类型是否可以静态转换为另一个指针类型 背景

C++ 使用SFINAE测试指针类型是否可以静态转换为另一个指针类型 背景,c++,c++14,sfinae,static-cast,C++,C++14,Sfinae,Static Cast,我正在写一个可移动的QScopedPointer;基本上std::unique_指针,带有一些额外的访问器。我在使用与C++11兼容的编译器之前就开始使用它,但现在我决定要正确使用它(尽管我正在重新发明轮子) 问题 让我们调用我的智能指针MyUniquePointer 我需要知道类型U*是否可以通过static\U cast转换为类型T*,具体如下: template<class T, class Cleanup> class MyUniquePointer { ... templa

我正在写一个可移动的
QScopedPointer
;基本上
std::unique_指针
,带有一些额外的访问器。我在使用与C++11兼容的编译器之前就开始使用它,但现在我决定要正确使用它(尽管我正在重新发明轮子)

问题 让我们调用我的智能指针
MyUniquePointer

我需要知道类型
U*
是否可以通过
static\U cast
转换为类型
T*
,具体如下:

template<class T, class Cleanup>
class MyUniquePointer
{
...
template<class U, class CleanupU, class = std::enable_if_t<detail::is_safely_castable<U, T>()>
MyUniquePointer(MyUniquePointer<U, CleanupU> && other) noexcept
    : d(static_cast<T *>(other.release()))
{}
...

返回:

Base to base:        true
Base to derived:     true
Derived to base:     true
Unrelated to base:   false
uint32 to uint64:    false
uint64 to uint32:    false
Base to void:        true
Void to derived:     true
Convertible to base: false
Base to convertible: false
-----------
Base to base:        true
Base to derived:     false
Derived to base:     true
Unrelated to base:   false
uint32 to uint64:    false
uint64 to uint32:    false
Base to void:        true
Void to derived:     true
Convertible to base: false
Base to convertible: false
我的问题的后半部分是这个解决方案是否在正确的轨道上,更具体地说,如果
| | std::is_convertible()
包括。传递时是否可以让
Is_convertible
返回true 指向类型作为模板参数的指针?上面的代码包括我自己的笨拙尝试,以使其工作

脚注:我知道
base\u type*
成功地转换为
派生的\u type*
,但我不是编译器,无法做出这样的假设。

似乎您想要:

template <typename T, typename U, typename = void>
struct is_safely_castable : std::false_type {};

template <typename T, typename U>
struct is_safely_castable<T, U,
                          std::void_t<decltype(static_cast<U>(std::declval<T>()))>>
: std::true_type
{};
模板
结构是_安全_可浇铸的:std::false _type{};
模板
结构是安全的浇注料
:std::true\u类型
{};

“您不能使用std::declval()的地址。”
&std::declval()
或者干脆
std::declval()
&std::declval()
,这不会起作用,但建议的变体应该可以起作用。现在看一下,我不知道
std::declval()
会让你假装构造一个指向假装对象的指针。我想你会得到一个类型为
T
的假指针,它什么也没有指向。哇<代码>无效\u t用于救援。我明白了,但是你能解释一下吗?这样我就可以接受这个答案了?
void\t
是使用SFINAE的一种方法。只有当
static\u cast
是正确的时,专门化才是正确的,否则,我们退回到一般情况,即
false\u type
template <typename T, typename U, typename = void>
struct is_safely_castable : std::false_type {};

template <typename T, typename U>
struct is_safely_castable<T, U,
                          std::void_t<decltype(static_cast<U>(std::declval<T>()))>>
: std::true_type
{};