提问人:Prismatic 提问时间:12/20/2014 最后编辑:Michael GazondaPrismatic 更新时间:12/22/2014 访问量:623
模板别名shared_ptr和unique_ptr时是否有任何问题或限制?
Are there any gotchas or limitations when template aliasing shared_ptr and unique_ptr?
问:
出于减少键入以下内容的简单原因:
std::shared_ptr<...>;
std::unique_ptr<...>;
每次我想使用智能指针时,我都会考虑使用模板别名:
template <typename T> using sptr = std::shared_ptr<T>;
template <typename T> using uptr = std::unique_ptr<T>;
所以我可以像这样使用它们:
sptr<...>;
uptr<...>;
假设我在自己的命名空间中保护它们,以这种方式使用带有共享/unique_ptr的模板别名是否有任何问题或限制?我是否永远无法用直接模板语法做一些我不能用别名做的事情?出于其他原因,这是一个坏主意吗?
答:
这很好,不会对您的代码产生不可预见的后果。
在您的示例中,和 将与 和 相同。您甚至可以使用静态断言来验证这一点:std::unique_ptr<T>
std::shared_ptr<T>
uptr<T>
sptr<T>
static_assert(std::is_same<std::shared_ptr<T>, sptr<T>>::value, "");
使用别名声明被视为完全相同的类型。不仅“相似”,而且完全相同。这就是可以继续进行而不必担心以后任何后果的原因。
您的别名声明将来唯一会限制的是您将其他参数传递给类型以外的智能指针的能力,例如 可以接受删除程序。如果您愿意,您可以修改您的 using 声明以包含带有可选 deleter 参数的更完整的定义,尽管我希望大多数人永远不会使用此功能。std::unique_ptr
另一方面,要记住的另一件事是还有谁会阅读你的代码? 它是什么很清楚,但不太清楚。或者更确切地说,也许不是“不太清楚”,而是需要理解。它为坐下来查看您的代码的人增加了一个减速带,因为他们需要在内部翻译 和 和 .std::shared_ptr
sptr
uptr
sptr
unique_ptr
shared_ptr
引用标准 (7.1.3)
使用 typedef 说明符声明的名称将变为 typedef-name。 在其声明的范围内,typedef-name 在语法上是 等同于关键字,并命名与 以第 8 条所述方式的标识符。因此,typedef-name 是一个 另一种类型的同义词。typedef-name 不会引入新类型 类声明 (9.1) 或枚举声明的方式。
typedef-name 也可以由 alias-declaration 引入。这 using 关键字后面的标识符将变为 typedef-name,并且 identifier appertains 后面的可选 attribute-specifier-seq 添加到该 typedef-name。它具有相同的语义,就好像它是 由 typedef 说明符引入。特别是,它没有定义 新类型,则不得出现在类型 ID 中。
答案已经给出,在你的情况下,它是一样的,但模板别名有时可能真的会引入新名称,这里有一个例子
#include <type_traits>
template <typename T> class A {};
template <typename T> using B = A<T>;
template < template <typename T> class S> class C {};
static_assert( std::is_same< A<int>, B<int> >::value, "same :)"); // they are the same
static_assert( std::is_same< C<A>, C<B> >::value, "not the same :("); // error, not the same
在这里,即使 和 是相同的,也是不同的。A
B
C<A>
C<B>
不要那样做。
是的,你当然可以这样做,但你应该这样做吗?IHMO,它使你的代码可读性降低,因为每个人都知道什么是,但没有人知道什么是,除了写那个奇怪代码的人......std::unique_ptr<>
uptr<>
良好的可维护代码易于阅读,使用类型和值的名称来表达其目的和意图,因此只需要最少的注释(避免注释,因为它们难以维护)。随着你的短,你正在离开这条智慧之路......uptr<>
当然,您可以使用更具描述性的名称,例如(在评论中建议)并使用 typedefs 通过实现它,或者,如果它不可用,(尽管如果您没有,我会认为您也没有移动语义,因此整个重点都丢失了)。但这不会帮助你减少打字。unique_pointer
std::unique_ptr
boost::unique_ptr
std::unique_ptr
unique_pointer
评论
unique_pointer
std::unique_ptr
unique_pointer
boost::unique_ptr
unique_pointer
unique_pointer
对于 ,通过std::shared_ptr<T
template <typename T>
using sptr = std::shared_ptr<T>;
因为根据定义,这些名称是等效的。
唯一指针是另一回事,因为您忽略了模板参数。因此,您只能获得 的默认模板参数,这限制了 over 的用例。uptr
uptr
unique_ptr
考虑以下一小段代码:
std::unique_ptr<FILE, void (*)(FILE*)> file(fopen("myfile.txt", "r"), [](FILE* f)
{
fclose(f);
});
// use file here to perform input operations
// automatic call to fclose at the end of scope (or any scope exit)
在这里,删除器的默认类型(即 )被替换以正确关闭 .这很重要,因为没有编辑。这也适用于任何 C 接口,其中您需要代替 ,因为默认的删除器 s,这与 ing 是不同的东西。std::default_delete<T>
FILE*
FILE*
new
free
delete
delete
free
你不能支持它,因为它是 a 而不是 .uptr<T>
template <typename T> using uptr<T> = ...
template <typename T, typename D = std::default_deleter<T>> using uptr<T, D> = ...
如果您对使用不同的删除器不感兴趣,那么重命名为 也没有什么坏处,因为类型完全相同。unique_ptr
uptr
上一个:使用指令组织,重新运行测试?
下一个:如何将类的静态方法引入命名空间?
评论