Difference between std::vector::empty and std::empty - c++

To check if a vector v is empty, I can use std::empty(v) or v.empty(). I looked at the signatures on cppreference, but am lacking the knowledge to make sense of them. How do they relate to each other? Does one implementation call the other?
I know that one comes from the containers library and the other from the iterators library, but that is about it.

Difference between std::vector::empty and std::empty
The difference between Container::empty member function and std::empty free function (template) is the same as difference between Container::size,std::size, Container::data,std::data, Container::begin,std::begin and Container::end,std::end.
In all of these cases for any standard container, the free function (such as std::empty) simply calls the corresponding member function. The purpose for the existence of the free function is to provide a uniform interface between containers (and also std::initializer_list) and arrays. Arrays cannot have member functions like the class templates can have, so they have specialised overload for these free functions.
If you are writing code with a templated container type, then you should be using the free function in order to be able to support array as the templated type. If the type isn't templated, then there is no difference between the choice of using member function or the free function other than the convenience of potential refactoring into a template (or just plain array).

There are three overloads of std::empty, but the one used by std::empty(v) for a vector v is the first:
template <class C>
constexpr auto empty(const C& c) -> decltype(c.empty()); // (since c++17, until c++20)
template <class C>
[[nodiscard]] constexpr auto empty(const C& c) -> decltype(c.empty());
(since C++20) // (since c++20)
This overload has the following effect:
returns c.empty()
So, std::empty(v) and v.empty() have the same effect in this case.

std::empty returns the result of calling std::vector::empty.
std::empty is useful for scenarios where a container may or may not provide a member function empty() for types providing a member function empty, std::empty provides a default implementation, but for a custom type not providing this function you can provide a function empty at namespace scope for use in templates; thanks to argument dependent lookup the function in the same namespace as the parameter will be used as fallback:
namespace Custom
{
struct Container
{
bool m_empty;
};
constexpr bool empty(Container const& c) // custom implementation for our own type
{
return c.m_empty;
}
}
template<class T>
void PrintEmpty(char const* containerName, T&& container)
{
using namespace std;
std::cout << containerName << " is " << (empty(container) ? "empty" : "not empty") << '\n';
}
int main()
{
PrintEmpty("std::vector<int>()", std::vector<int>());
PrintEmpty("Container{}", Custom::Container{});
PrintEmpty("Container{ true }", Custom::Container{ true });
}

To language-lawyer a bit, the C++20 standard says that a container a has its a.empty() member function return true if and only if a.begin() == a.end() ([container.requirements.general]).
The std::empty() non-member function is specified in [iterator.range]. The overload constexpr auto empty(const C& c) “Returns: c.empty().”
So, in the Standard, the non-member function is specified in terms of the member functions, not vice versa. In general, that doesn’t mean that the implementation needs to have the non-member function actually call the member function, so long as it “behaves as if.” In this case, the relationship must hold for any allowed specialization of the STL container classes, or for custom container classes, so that constrains what the writers of the library are allowed to do.

Related

How do you define emplace_back and other variadic template functions in a C++ concept?

I'm trying to define a C++ concept for standard library containers that allow push_back/emplace_back:
template <class ContainerType>
concept PushBackContainer = requires(ContainerType a)
{
requires SequenceContainer<ContainerType>;
{ a.push_back(typename ContainerType::const_reference& v) };
{ a.push_back(typename ContainerType::value_type&& v) };
// How do you define a variable templated function:
{ template< class... Args > a.emplace_back(Args&&... args) };
}
The problem I have is how do I define emplace_back with its variadic template arguments? I'm using Visual Studio 2019 but if this isn't supported I'd be interested in the correct syntax come the time it is.
Probably about the best that's worth doing is just a.emplace_back();.
Your push_back requirements don't have a correct syntax, either. I think you want:
template <class ContainerType>
concept PushBackContainer = requires(
ContainerType& a,
typename ContainerType::value_type const& cv,
typename ContainerType::value_type& v)
{
requires SequenceContainer<ContainerType>;
a.push_back(cv);
a.push_back(std::move(v));
a.emplace_back();
};
Requirements don't check for a function signature; they check for the validity of an expression (without instantiating more templates than necessary). If we had a class like:
class StrangeContainer {
public:
using value_type = std::string;
using const_reference = const value_type&;
private:
struct ValueHolder {
ValueHolder(const std::string& s) : value(s) {}
ValueHolder(std::string&& s) : value(std::move(s)) {}
std::string value;
};
public:
void push_back(ValueHolder);
template <typename ... Args>
void emplace_back(Args&&...);
};
then ignoring SequenceContainer requirements, PushBackContainer<StrangeContainer> would be true, and it would also satisfy the Standard's own requirements related to push_back. It satisfies the technical requirements, even though it has some surprising effects like the fact that push_back("") is ill-formed.
So for push_back, we're really just checking that it can be called with a const lvalue and with a non-const rvalue. (The Standard actually also requires that it can be called with a non-const lvalue and with a const rvalue, and these cases have the same behavior as when called with a const lvalue.)
(If you really wanted to test for an exact push_back signature, you could try static_cast<void (ContainerType::*)(typename ContainerType::value_type&&)>(&ContainerType::push_back); - but this is not recommended, since member functions in namespace std are not required to have signatures exactly as described, only to be callable with the same arguments as if declared as described.)
Also, the standard container class templates don't have any constraints on their push_back or emplace_back functions. Every instantiation of the templates which have push_back declares both overloads, whether or not the type is copyable and/or movable. If not, it would be an error to actually call or otherwise odr-use the push_back function, but it "exists" for purposes of requires-expressions and SFINAE contexts. Likewise, the emplace_back member template is declared to accept any number of arguments with any types and value categories, no matter whether they can be used as value_type constructor arguments or not.
So what we would want to test to find out if the container has an emplace_back with an essentially ordinary variadic function declaration would need to be phrased as: Can emplace_back be called with any number of arguments, with each having any possible type and each being either an lvalue or rvalue? I don't think there's any way to really answer that within C++, using requires-expressions, SFINAE tricks, or otherwise. So I would just do one simple test for existence of some sort of emplace_back, and that test might as well be as simple as possible: zero arguments.
You could get fancier and also test for some additional cases: Does emplace_back accept different numbers of arguments, up to some fixed maximum? Does it accept lvalue and rvalue arguments? Does it accept arguments of dummy struct types? Dummy struct types that aren't MoveConstructible? const, volatile, and const volatile types? All possible combinations of all of the above? But since you'll never cover all the cases, how much value does each partial enhancement like this really give, compared to the effort, complexity, and maintenance needed to add checks?

Can I use the iterator Libraries' Access Functions on Nonstandard Containers?

The iterator library has been introducing a lot of access functions over the course of C++11, C++14, and C++17:
begin/end
cbegin/cend
crbegin/crend
data
empty
rbegin/rend
size
Can I use these on any container, even nonstandard containers (provided they supply an accessible corresponding method?) For example given a QVector foo can I do this:
const auto bar = begin(foo);
The declarations for std::begin are as follow (from §24.7):
template <class C> auto begin(C& c) -> decltype(c.begin());
template <class C> auto begin(const C& c) -> decltype(c.begin());
So these functions will be defined for any class C such that c.begin() is "valid" (does exist). The standard also guarantees that these will:
Returns: c.begin().
So yes you can use begin(c) on any container of type C as long as either:
The member function C::begin() is provided.
There exist a begin(C const&) or begin(C &) function.
The standalone begin function should not be in the std:: namespace but rather in the same namespace as your class C so name-lookup can find it.
As I understand it, your question seem to be: if the container provides a member function begin, can I then call it as a free function? The answer to your question is yes, because a templated free function begin is provided by the standard, that simply tries to call the member function begin; from http://en.cppreference.com/w/cpp/iterator/begin: "Returns an iterator to the beginning of the given container c or array array. These templates rely on C::begin() having a reasonable implementation.".

Generic lambdas Vs Standard template functions (What to use and When)

Generic Lambdas are a way of defining lambdas that read as follows:
auto identity = [](auto a){return a;}
Compare this with:
template <typename T>
T Identity(T t){return t;}
or with
template <typename T>
struct Identity { T operator()(T a) { return a; } };
This is my understanding
lambdas allow context capture using [&], [=], etc, I am not sure how this will be used / applied in generic lambdas. Is this the main difference ?
generic lambdas can be cast to function pointers whereas, template specialisation can be cast to function pointers.
A simple real world example will be useful to understand what to use and when.
[Appended] Here is the generic lambda proposal : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3559.pdf
Pretty much like lambdas, generic lambdas are defined through equivalence to an implicitly defined function object (where non-generic lambdas have the additional ability that with empty capture they can convert to a function pointer). The only real difference between generic and non-generic lambdas is that generic lambda have call operator which is a function template while it is a non-template for non-generic lambdas.
For generic lambdas the conversion to function pointers doesn't exist (see 5.1.2 [expr.prim.lambda] paragraph 6).
Since generic lambdas are still objects with a call operator, they can be used directly as an argument where a generic function objects can be used. That is not the case for a function templates: these behave more like an overload set and you need to get the instantiated before you can pass them as a function object.
Although you can't get a pointer to a function template, you can get a pointer to a function template specialization (as #Columbo pointed out in a comment, a function template specialization is a function). You can't get a pointer to a function out of a generic lambda.
Function templates participate in overload resolution while function objects don't really participate: when an object is found during name look-up this object is chosen even if there could be functions found with the same name and with a nice match for overloading. This implies, that these two are not equivalent:
template <typename T>
auto identity(T value) { return value; }
auto identity = [](auto value) { return value; }
The second implementation hijacks the name while the former is used as a candidate in overload resolution.
Aside from auxiliary objects created from within a function I would use generic lambdas for functions which are not meant as customization points (e.g. it would be nice if standard library algorithms were such objects). The main benefit is that function objects can be readily adapted, e.g., using std::bind() which is not true for function templates.

Template functions versus named lambdas with auto parameters

What are the differences between
template <typename T> void func( T t ) { /* ... */ }
and the C++14 alternative using lambdas with auto parameters?
auto func = []( auto t ) { /* ... */ }
Which one should be preferred?
The first is a function template. It can be specialized and overloaded. It can be found by ADL. When you want to take the address, you must either explicitly give it template parameters or do it in a context where the compiler can deduce them.
The second, assuming it appears on namespace scope, is a global object with a templated function call operator. It cannot be specialized or overloaded (global variables conflict with functions, they don't overload them). It cannot be found by ADL (ADL only finds functions and function templates). If you use the address operator on it, you get the address of the object, which is pretty useless. The object itself can be converted to a function pointer if the compiler can deduce the arguments; you cannot supply them explicitly.
You can use whichever you want; just be aware of the advantages and disadvantages of either choice. I would recommend the first. The only advantage of the second is its terseness, and I hope we'll get terse syntax for function templates in the not-too-distant future as well.
auto func(auto t) { ... }
The difference is that the first one is function template which you have to define before you use it; once the definition is there, anyone can use it. So it is a reusable piece of code and remains there forever.
Lambdas, on the other hand, are handy: you can define it when you need it. If the lambda is defined inside a function, as a local object, then only that function can use it and pass it to other functions. It is still reusuable, but less than function template. However lambdas, defined at namespace level, is as reusable as function template, because anyone can use it. So it is not much different from function template when you define it at namespace level. There can be some corner cases to be discovered by experts. One such case is, you can specialize function template:
//specialization : possible only in case of template!
template<> void func(MyClass obj) { /* ... */ }
You cannot do this with lambdas!
N3337, [expr.prim.lambda]/3:
The type of the lambda-expression (which is also the type of the
closure object) is a unique, unnamed nonunion class type — called the
closure type — whose properties are described below. This class type
is not an aggregate (8.5.1). The closure type is declared in the
smallest block scope, class scope, or namespace scope that contains
the corresponding lambda-expression.
This closure type will stay a class. But its overloaded function call operator will be a operator function template, allowing different specializations. Furthermore, unlike function templates, you can implicitely convert a closure object to a function pointer. Its really handy, isn't it?
Quoting N3559, it'll look something like that:
For a generic lambda L:
int(*fp)(int, char) = [](auto a, auto b){return a+b;};
The closure type is
struct/*anonymous*/
{
template<class A,class B>
auto operator()(A a,B b) const
{
return a+b;
}
private:
template<class A,class B>
static auto __invoke(A a,B b)
{
return a+b;
}
template<class A,class B,class R>
using fptr_t = R(*)(A,B);
public:
template<class A,class B,class R>
operator fptr_t<R,A,B>() const
{
return &__invoke<A,B>; // Fixed that manually, they forgot to qualify the template name
}
} L;
int(*fp)(int,char) = L;
(There will be usual template argument deduction performed)

Why doesn't unary_function define operator()?

I was just looking for a handy base class for a set of functors to be based on taking and int and returning void.
Thinking to use std/functional the functors are basically going to be unary_function<int,void> with operator().
Why is virtual result_type operator()(const argument_type& _Left) const = 0; not defined on the unary_function template? I'm guessing that it's because there could be variations in constness...
Is there some other template I've missed that includes the operator()?
I haven't done this in a while, am I missing something?
How would I also make use of existing functional like
std::ptr_fun< HWND, void >(someFunction);
std::pointer_to_unary_function<HWND, void>(someFunction);
EDIT:
Perhaps I should include the other half of the usage to make this complete. Maybe it's the usage half that is not fitting in with the concept.
How would one pass the functor to a method and use it?
typedef unary_function<int,void> Functor;
void DoStuff(const Functor& functor) {
int demo = 1;
functor(demo);
}
functor as a unary_function doesn't define operator() and so DoStuff doesn't compile.
Template concepts are duck-typed. The fact that a class satisfying the UnaryFunction concept needs operator() is specified in the documentation and inferred from the templates which use template parameters satisfying that concept. There's no need to spell out the function signature, or to require that it be virtual, that it take a const reference parameter, or that it be a const member function.
The unary_function template should not be thought of as an interface (and it isn't designed as one). It's certainly not a polymorphic base class. It's a helper, which is used by classes that wish to implement the AdaptableUnaryFunction concept.
From the STL docs, which are reliable for the original design rationale: "the only reason it exists is to make defining Adaptable Unary Functions more convenient" - http://www.sgi.com/tech/stl/unary_function.html
The standard is similar: "The following classes are provided to simplify the typedefs of the argument and result types" (20.3.1/1)
Advanced usage - actually what's required for UnaryFunction is that if f is a unary function object, and x is convertible to the argument type, then f(x) is a valid expression of the result type. It needn't have a one-argument operator() at all, it's fine to have a two-arg operator() with the second arg having a default value. Try defining that as a pure virtual function ;-)
Second question, you make use of ptr_fun just by calling it with function name/pointer. Its template parameters will be inferred from the function type, so you don't need to specify them. The result is an object of the corresponding pointer_to_unary_function template type.
To use the example straight from the STL docs:
transform(first, last, first,
compose1(negate<double>, ptr_fun(fabs)));
This is approximately equivalent to:
for (auto current = first; current != last; ++current) {
*current = -fabs(*current);
}
(where I use auto in its C++0x sense, meaning "I cannot be bothered / it is impossible to write the iterator type here")
A function name/pointer can be used in transform (which takes a UnaryFunction template parameter), but not in compose1 (which takes an AdapatableUnaryFunction template parameter). So without ptr_fun, there's no way to compose negate with fabs.
In response to your Edit, I stress, unary_function is not a polymorphic base class. You cannot usefully use it (or any of its instantiations) as a function parameter type.
If you want to use the UnaryFunction or AdaptableUnaryFunction concepts, then you must write a function template:
template <typename UnaryFunction>
void DoStuff(UnaryFunction &functor) {
int demo = 1;
functor(demo);
}
This only requires that the functor take a type which int converts to, though. It doesn't require that it take exactly int and return exactly void. That's usually an advantage.
If a template doesn't do what you want, then unary_function is not for you. You haven't missed anything: you can design your own interface with a virtual operator(), but the standard libraries don't aim to provide any such thing.
Because a virtual operator () is not a part of the unary_function concept. The unary function concept can have a non-virtual operator in addition to differences in constness.