C++ 如何断言向量中的所有 std::shared_ptr 都指向某物
c++ how to assert that all std::shared_ptr in a vector are referring to something
当我有一个函数接收一个应该指向某物的(智能)指针时,我总是这样开始:
class Foo;
void doSomething(const std::shared_ptr<Foo>& pFoo)
{
assert(pFoo);
// ...
}
现在我正在为(智能)指针的向量(或其他容器)寻找类似的断言条件。我能想到的最好的是:
void doSomething(const std::vector<std::shared_ptr<Foo> >& pFoos)
{
assert(std::all_of(pFoos.begin(), pFoos.end(), [](const std::shared_ptr<Foo>& pFoo) { return pFoo; }));
// ...
}
我想知道这是否可以改进.. 可以避免 lambda 吗? (我尝试使用 shared_ptr 的 get() 方法,但模板推导失败了)或者是否有另一种方法来断言整个容器?
您可以使用实现您自己的实用谓词:
struct is_nullptr
{
template <typename T>
bool operator()(T&& x) const noexcept { return x == nullptr; }
};
void doSomething(const std::vector<std::shared_ptr<Foo> >& pFoos)
{
assert(!std::any_of(pFoos.begin(), pFoos.end(), is_nullptr{});
// ...
}
And/or你自己的"range assertion":
template <typename TContainer, typename TPredicate>
void range_assert(TContainer&& container, TPredicate&& p)
{
for(auto&& x : container)
{
assert(p(x));
}
}
void doSomething(const std::vector<std::shared_ptr<Foo> >& pFoos)
{
range_assert(pFoos, [](const std::shared_ptr<Foo>& x) { return x; });
// ...
}
另一种仅使用标准功能来表达它的稍微复杂的方式:
assert(std::none_of(pFoos.begin(), pFoos.end(), std::logical_not<std::shared_ptr<Foo>>{}));
从 C++14 开始,您可以使用 std::logical_not
的泛型特化:
assert(std::none_of(pFoos.begin(), pFoos.end(), std::logical_not<>{}));
另一种方法:
assert(std::find(pFoos.begin(), pFoos.end(), nullptr) == pFoos.end());
当我有一个函数接收一个应该指向某物的(智能)指针时,我总是这样开始:
class Foo;
void doSomething(const std::shared_ptr<Foo>& pFoo)
{
assert(pFoo);
// ...
}
现在我正在为(智能)指针的向量(或其他容器)寻找类似的断言条件。我能想到的最好的是:
void doSomething(const std::vector<std::shared_ptr<Foo> >& pFoos)
{
assert(std::all_of(pFoos.begin(), pFoos.end(), [](const std::shared_ptr<Foo>& pFoo) { return pFoo; }));
// ...
}
我想知道这是否可以改进.. 可以避免 lambda 吗? (我尝试使用 shared_ptr 的 get() 方法,但模板推导失败了)或者是否有另一种方法来断言整个容器?
您可以使用实现您自己的实用谓词:
struct is_nullptr
{
template <typename T>
bool operator()(T&& x) const noexcept { return x == nullptr; }
};
void doSomething(const std::vector<std::shared_ptr<Foo> >& pFoos)
{
assert(!std::any_of(pFoos.begin(), pFoos.end(), is_nullptr{});
// ...
}
And/or你自己的"range assertion":
template <typename TContainer, typename TPredicate>
void range_assert(TContainer&& container, TPredicate&& p)
{
for(auto&& x : container)
{
assert(p(x));
}
}
void doSomething(const std::vector<std::shared_ptr<Foo> >& pFoos)
{
range_assert(pFoos, [](const std::shared_ptr<Foo>& x) { return x; });
// ...
}
另一种仅使用标准功能来表达它的稍微复杂的方式:
assert(std::none_of(pFoos.begin(), pFoos.end(), std::logical_not<std::shared_ptr<Foo>>{}));
从 C++14 开始,您可以使用 std::logical_not
的泛型特化:
assert(std::none_of(pFoos.begin(), pFoos.end(), std::logical_not<>{}));
另一种方法:
assert(std::find(pFoos.begin(), pFoos.end(), nullptr) == pFoos.end());