In the docs on std::span constructors, there isn't one that accepts an std::vector.
Then, how come this code (source page) compiles?
// createSpan.cpp
#include <algorithm>
#include <iostream>
#include <span>
#include <vector>
int main() {
std::cout << std::endl;
std::cout << std::boolalpha;
std::vector myVec{1, 2, 3, 4, 5};
std::span mySpan1{myVec}; // (1)
std::span mySpan2{myVec.data(), myVec.size()}; // (2)
bool spansEqual = std::equal(mySpan1.begin(), mySpan1.end(),
mySpan2.begin(), mySpan2.end());
std::cout << "mySpan1 == mySpan2: " << spansEqual << std::endl; // (3)
std::cout << std::endl;
}
i.e. which constructor of std::span was invoked at (1)?
It's the constructor (7) in the overload set:
template< class R >
explicit(extent != std::dynamic_extent)
constexpr span( R&& r );
From the explanation:
Constructs a span that is a view over the range r; the resulting span has size() == std::ranges::size(r) and data() == std::ranges::data(r).
There are further restriction on when this signature takes part in overload resolution, but that's the essence. And std::vector satisfies these requirements.
It's a good thing that this is kept only as constrained as necessary, because it allows custom (non-std) containers to allow for implicit conversion to std::span instances.
Related
std::array has a built-in method empty() to check if the array is empty. As shown in the example copied from here:
#include <array>
#include <iostream>
int main()
{
std::array<int, 4> numbers {3, 1, 4, 1};
std::array<int, 0> no_numbers;
std::cout << std::boolalpha;
std::cout << "numbers.empty(): " << numbers.empty() << '\n';
std::cout << "no_numbers.empty(): " << no_numbers.empty() << '\n';
}
Are there any ways to check if the array is declared, with some fixed size, but not explicitly initialized?
Say, something like this?
std::array<int,4> a;
std::array<int,4> b;
a = {1,2,3,4}; //a holds some explicit values
//do not assign values to b
//how to tell the different state of a and b?
No. std::array<T, N>::empty() where N!=0 will always return false. https://en.cppreference.com/w/cpp/container/array/empty "Checks if the container has no elements, i.e. whether begin() == end()."
Similarly std::array<T, 0>::empty() will always return true, because begin() == end().
The size of a std::array object (that is, the number of elements it has) must be a compile-time constant, and cannot be changed dynamically. Thus, the empty() and size() member functions would perhaps seem somewhat redundant†(but included for reasons of compatibility with generic, container-based algorithms provided by the STL).
If you need a container with a size that can be changed, then you should use std::vector instead of std::array (although this has more run-time overheads).
The following illustrates one of the differences:
#include <iostream>
#include <array>
#include <vector>
int main()
{
std::array<int, 4> a;
std::array<int, 4> b;
a = { 1,2,3,4 }; //a holds some explicit values
std::cout << std::boolalpha;
std::cout << "a.empty(): " << a.empty() << '\n'; // false
std::cout << "b.empty(): " << b.empty() << '\n'; // false
// However ...
std::vector<int> v1;
std::vector<int> v2;
v1 = { 1,2,3,4 };
std::cout << "v1.empty(): " << v1.empty() << '\n'; // false
std::cout << "v2.empty(): " << v2.empty() << '\n'; // true
return 0;
}
†But note, those members are useful for cases when an array is passed to a function, which otherwise would not be able to determine the size (or emptiness) of its given argument(s).
I don't understand what you're asking for:
Are there any ways to check if the array is declared, with some fixed size, but not explicitly initialized?
If you have a variable of type std::array, then it has been constructed.
If it's been constructed, then the elements in the array have been constructed.
(that's done in the array constructor)
This variable std::array<std::string, 5> sa; contains 5 default-constructed strings.
So I don't know what you mean by "declared, but not explicitly initialized"
Before marking this as duplicate, I have been here, here, and here, a duplicate of the first.
I'm aware of boost::multi_index, and use an environment where I lack it, and that a std::unordered_set is not bound to store elements in a deterministic insertion order.
I find the concept of using two containers, say an additional std::vector as uncouth.
What I would love is a solution involving a comparator that I can use in a std::set's template parameters (clarification, this could be a trivial functor struct, containing a bool operator()() overload, a regular function, or a lambda). Is it possible?
Addenda
Initialization must occur through a std:: container's begin iterator/end iterator constructor, such as in this snippet.
std::string str; cin >> str;
std::set<char>(str.begin(), str.end());
Also, another interesting use-case would be to create a dumb hash wrapping functor that allows insertion order to be pushed in to a std::unordered_set's template parameter.
You cannot directly have a lambda expression as the set's template parameter, because a lambda expression is a value, and the set's template parameter is a type. The obvious correction of the question, whether a construction using a lambda and decltype can work, leads to the interesting problem that a lambda expression denotes a unique type (a "closure type"), so you can never make two separate lambda expressions of the same closure type.*
However, in a more abstract sense what you want can be achieved in a local context using template argument deduction, for example:
template <typename F>
int f(int* first, int* last, F comp)
{
std::set<int, F> s(comp);
while (first != last) s.insert(*first++);
...
}
Now you can call f with a lambda expression as the argument, thus effectively "using a lambda as the set's comparator". Or, for a simpler example, you could just have a named variable for the lambda (putting all the template deduction into a single auto:
auto comp = [](...) { ... };
std::set<int, decltype(comp)> s(comp);
*) There is a proposal to allow lambdas in unevaluated contexts to address this point, but its outlook is uncertain. It has interesting side effects like making closure types affect name mangling.
An adt that preserves the order of insertion is an std::vector.
You can just as easily wrap it like this to get an std::set-like behavior:
#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
using namespace std;
template < typename T >
class VectorSet : public vector<T> {
public:
using iterator = typename vector<T>::iterator;
using value_type = typename vector<T>::value_type;
pair<iterator, bool> insert (const value_type& val) {
auto it = ::find(this->begin(), this->end(), val);
if (it == this->end())
it = ::vector<T>::insert(this->end(), val);
return pair<iterator, bool>(it, true);
}
};
int main()
{
VectorSet<int> my;
my.insert(1);
my.insert(4);
my.insert(3);
my.insert(4);
for (auto & v : my) {
cout << v << endl;
}
return 0;
}
You cannot, unless you use additional indexes. Two approaches:
1. using an explicit index
Live On Coliru
#include <set>
#include <vector>
#include <functional>
#include <algorithm>
using namespace std;
#include <iostream>
string read_word() {
string str;
cin >> str;
return str;
}
int main() {
using Ref = std::reference_wrapper<char const>;
auto const str = read_word();
std::cout << "Word: " << str << "\n";
auto v = [&]() -> vector<Ref> {
set<Ref> u(str.begin(), str.end());
return {u.begin(), u.end()};
}();
std::cout << "Unique: " << string(v.begin(), v.end()) << "\n";
auto pos = [str](char ch) { return str.find(ch); };
std::sort(v.begin(), v.end(), [pos](auto& a, auto& b) { return pos(a) < pos(b); });
std::cout << "Insertion: " << string(v.begin(), v.end()) << "\n";
}
Prints e.g.
Word: pineapple
Unique: aeilnp
Insertion: pineal
2. using Boost Multi-Index
Same deal
Live On Coliru
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
namespace bmi = boost::multi_index;
using Index = bmi::multi_index_container<char,
bmi::indexed_by<
bmi::sequenced<>,
bmi::ordered_unique<bmi::tag<struct unique>, bmi::identity<char> >
> > ;
#include <iostream>
std::string read_word() {
std::string str;
std::cin >> str;
return str;
}
int main() {
auto const str = read_word();
std::cout << "Word: " << str << "\n";
Index idx(str.begin(), str.end());
std::cout << "Insertion: " << std::string(idx.begin(), idx.end()) << "\n";
auto& u = idx.get<unique>();
std::cout << "Unique: " << std::string(u.begin(), u.end()) << "\n";
}
Prints
Word: pineapple
Insertion: pineal
Unique: aeilnp
I thought a weird solution (though not one involving any sets) could be to use a std::map of the element type and std::time_point as the key type. That will ensure insertion order if not anything at all.
I have read many posts about variadic templates and std::bind but I think I am still not understanding how they work together. I think my concepts are a little hazy when it comes to using variadic templates, what std::bind is used for and how they all tie together.
In the following code my lambda uses the dot operator with objects of type TestClass but even when I pass in objects of type std::ref they still work. How is this exactly? How does the implicit conversion happen?
#include <iostream>
using std::cout;
using std::endl;
#include <functional>
#include <utility>
using std::forward;
class TestClass {
public:
TestClass(const TestClass& other) {
this->integer = other.integer;
cout << "Copy constructed" << endl;
}
TestClass() : integer(0) {
cout << "Default constructed" << endl;
}
TestClass(TestClass&& other) {
cout << "Move constructed" << endl;
this->integer = other.integer;
}
int integer;
};
template <typename FunctionType, typename ...Args>
void my_function(FunctionType function, Args&&... args) {
cout << "in function" << endl;
auto bound_function = std::bind(function, args...);
bound_function();
}
int main() {
auto my_lambda = [](const auto& one, const auto& two) {
cout << one.integer << two.integer << endl;
};
TestClass test1;
TestClass test2;
my_function(my_lambda, std::ref(test1), std::ref(test2));
return 0;
}
More specifically, I pass in two instances of a reference_wrapper with the two TestClass objects test1 and test2, but when I pass them to the lambda the . operator works magically. I would expect that you have use the ::get() function in the reference_wrapper to make this work but the call to the .integer data member works..
The reference unwrapping is performed by the result of std::bind():
If the argument is of type std::reference_wrapper<T> (for example, std::ref or std::cref was used in the initial call to bind), then the reference T& stored in the bound argument is passed to the invocable object.
Corresponding standardese can be found in N4140 draft, [func.bind.bind]/10.
It is important to note that with std::bind;
The arguments to bind are copied or moved, and are never passed by reference unless wrapped in std::ref or std::cref.
The "passed by reference" above is achieved because std::ref provides a result of std::reference_wrapper that is a value type that "wraps" the reference provided.
std::reference_wrapper is a class template that wraps a reference in a copyable, assignable object. It is frequently used as a mechanism to store references inside standard containers (like std::vector) which cannot normally hold references.
By way of an example of what bind's unwrapping of the reference does (without the bind);
#include <iostream>
#include <utility>
#include <functional>
int main()
{
using namespace std;
int a = 1;
auto b = std::ref(a);
int& c = b;
cout << a << " " << b << " " << c << " " << endl; // prints 1 1 1
c = 2;
cout << a << " " << b << " " << c << " " << endl; // prints 2 2 2
}
Demo code.
I have a data structure of the following form:
vector<pair<vector<unsigned>,vector<unsigned> > a;
Now I want to sort the vector "a" according to first vector of pair. E.g. in the example given below, I want to rank according to the following:
(((1,2,4),(89,29)) , ((1,3),(67,90))). As size of a3 is greater than size of a1, therefore ranking is done first according to a3 and then a1.
E.g. If
vector<unsigned> a1,a3;
a1.push_back(1); a1.push_back(3);
vector<unsigned> a2,a4;
a2.push_back(67); a2.push_back(90);
a.push_back(make_pair(a1,a2));
a3.push_back(1); a3.push_back(2); a3.push_back(4);
a4.push_back(89); a4.push_back(29);
a.push_back(make_pair(a3,a4));
I know I can do the sorting using bubble sort. But is there some other way in C++ like STL function to do the same.
Just use std::sort with a function object (a lambda here) that compares the first element of each pair (and which uses the operator< from std::vector)
#include <algorithm>
#include <iostream>
#include <utility>
#include <vector>
using namespace std;
int main()
{
vector<pair<vector<unsigned>,vector<unsigned> >> a = {{{1,3},{67, 90}}, {{1,2,4},{89,29}}};
sort(begin(a), end(a), [](auto const& L, auto const& R) {
return L.first < R.first;
});
for (auto const& elem : a) {
std::cout << "{{";
for (auto const& u : elem.first)
std::cout << u << ", ";
std::cout << "},";
std::cout << "{";
for (auto const& u : elem.second)
std::cout << u << ", ";
std::cout << "}},";
}
}
Live Example using C++14.
You can adapt it to C++98 by writing the range-based for loop using iterators / indices, and by writing a separate function object that you pass to std::sort. Oh, and you would also have to use the awkward push_back initialization instead of the more convenient initalizer-lists from C++11 and beyond.
Minimal working example:
#include <tuple>
struct example
{
example(int, char) {}
};
int main()
{
std::tuple<example, int, double>
my_tuple(example(0, 'x'), 42, .0);
// std::tuple t = make_my_tuple(0, 'x');
return 0;
}
This works.
Is there a more elegant way to initialize only the first member, like I sketched in the comment? One which only takes the arguments to construct the first tuple member and does not initialize the others?
The reason I ask? I am just interested in the semantics of the language.
You say that giving values for the other two members is not necessary - are you worried about performance? Or that there may be no suitable value for these members?
If it's the latter, you could have your tuple hold boost::optionals. e.g.
#include <tuple>
#include <boost/optional.hpp>
using namespace boost;
struct example
{
example(int, char) {}
};
typedef std::tuple<example, optional<int>, optional<double>> MyTuple;
int main()
{
MyTuple my_tuple(example(0, 'x'), optional<int>(), optional<double>());
return 0;
}
You now semantically have the int and float "uninitialised", and can query their value as such.
To make this more elegant, you can wrap this into a function, using the perfect forwarding idiom for the arguments (in general; in this case your arguments are cheap to copy, so no speed benefit from doing this):
template <class... Args>
MyTuple make_mytuple(Args&&... args)
{
return MyTuple(example(std::forward<Args>(args)...), optional<int>(), optional<double));
}
The advantage of this template is that it's resilient to changes in example's constructor. If you add another argument, just call make_mytuple with the new arguments and it will work.
Your other point about the copying in the tuple construction is valid, but in reality I believe this will be optimal on most compilers. (a combination of RVO and elision of copies when passing an rvalue to a function by value).
You can use uniform initialization. Sadly, you cannot define a default value, argument will be initialized with the default constructor or 0.
#include <iostream>
#include <tuple>
enum class Result {Full, Partial, Empty};
std::tuple<bool, int, double> get_tuple(Result type)
{
if (type == Result::Full)
return {true, 42, 3.14159};
else if (type == Result::Partial)
return {true, 42, {}};
else
return {};
}
int main()
{
bool b;
int i;
double d;
std::tie(b, i, d) = get_tuple(Result::Full);
std::cout << b << " " << i << " " << d << std::endl;
std::tie(b, i, d) = get_tuple(Result::Partial);
std::cout << b << " " << i << " " << d << std::endl;
std::tie(b, i, d) = get_tuple(Result::Empty);
std::cout << b << " " << i << " " << d << std::endl;
return 0;
}
output:
1 42 3.14159
1 42 0
0 0 0