我正在尝试创建一个通用的setter,支持值和指针.我的指针有问题.说明主要想法的最小代码:
#include <memory>
#include <variant>
class A{
int s;
};
template <typename uniq, typename ptr>
void set(uniq &u, const ptr &p){
u = std::unique_ptr<decltype(*std::declval<ptr>)>(p);
}
int main(){
std::variant<std::unique_ptr<A>> dd;
set(dd, new A);
}
Run Code Online (Sandbox Code Playgroud)
编译(gcc-7.3.0)失败了
no matching function for call to ‘std::unique_ptr<A*&& (&)() noexcept, std::default_delete<A*&& (&)() noexcept> >::unique_ptr(A* const&)’
Run Code Online (Sandbox Code Playgroud)
我没有关于如何获得指针类型的想法......另外,引用来自哪里?(更改ptr参数无法解决)
你刚才有一个错字:
template <typename uniq, typename ptr>
void set(uniq &u, const ptr &p){
u = std::unique_ptr<decltype(*std::declval<ptr>)>(p);
// ^^^
}
Run Code Online (Sandbox Code Playgroud)
std::declval是一个函数,所以你正在编写的代码试图取消引用该函数类型.这是有效的事情!这就是你得到的A*&& (&)() noexcept
你想要的是:
template <typename uniq, typename ptr>
void set(uniq &u, const ptr &p){
u = std::unique_ptr<decltype(*std::declval<ptr>())>(p);
}
Run Code Online (Sandbox Code Playgroud)
通过直接使用名称,您可以更简单地编写p:
template <typename uniq, typename ptr>
void set(uniq &u, const ptr &p){
u = std::unique_ptr<decltype(*p)>(p);
}
Run Code Online (Sandbox Code Playgroud)
但这可能实际上并不正确,因为它decltype(*p)通常具有引用类型,您必须将其删除:
template <typename uniq, typename ptr>
void set(uniq &u, const ptr &p){
u = std::unique_ptr<std::remove_reference_t<decltype(*p)>>(p);
}
Run Code Online (Sandbox Code Playgroud)
现在,这段代码真的只适用于原始指针(你必须使用movea unique_ptr并且你不能将a转换shared_ptr为a unique_ptr),所以你可以更清楚地表达在函数签名中,这也使得身体更容易编写:
template <typename uniq, typename T>
void set(uniq &u, T* p){
u = std::unique_ptr<T>(p);
}
Run Code Online (Sandbox Code Playgroud)
这最终引出了为什么要写的问题:
set(dd, new A);
Run Code Online (Sandbox Code Playgroud)
代替:
dd = std::make_unique<A>();
Run Code Online (Sandbox Code Playgroud)
无论如何?第二是远远优越.
| 归档时间: |
|
| 查看次数: |
64 次 |
| 最近记录: |