Make a user defined variable array - c++

I have to write a simple code that takes a char as input or a string with an integer. Then makes a std vector, depending on the input. If the text says int I have an int vector.
The only problem is that I don't want to declare for each variable type a vector even if empty, and I want to make it scalable so if someday I want to put a struct or something else in it i can.
dvec::dvec( char t){
if ( t=='i')
vector<int> a;
else if( t=='f')
vector<float> a;
}

If all you want is primitive types or pointers, you can make a union (8 bytes in size) and a vector of that union. It's a bit C'ish, but template is a compile time solution, so for a linkable solution, you need space for every type. You can have getters, setters, constructors for each type.

You can implement this thing in two ways:
1.
using element_type = std::variant<char, int, float /* ... other types */>;
using dvec = std::vector<element_type>;
This will be type safe, albeit the disadvantage is that every element of the vector is a variant, which might not be what you want.
2.
using dvec = std::variant<std::vector<char>,
std::vector<int>,
std::vector<float> /* ... other vector types */>;
This will give you a variant of vectors, where all vector elements are homogeneous.
This cumbersome expression could be simplified by using Boost.Mp11
template<class T> using vectorize_t = std::vector<T>;
template<typename ...T>
using dvec = std::variant<mp_transform<vectorize_t, T...>>;
which basically puts all respective types in T... to an std::vector.

Write a helper function to do the real work.
template <typename T>
void do_work() {
std::vector<T> a;
// do stuff
}
// ...
if(t == 'i') {
do_work<int>();
}
else if(t == 'f') {
do_work<float>();
}
else if(t == 's') {
do_work<your_struct>();
}
Depending on what your specific uses are you might need (or at least want) to have do_work just call multiple functions, that way you can specialize if needed.

Related

How to initialize a map of arrays of different sizes?

Simple question, how to initialize a map of arrays (or some other container type) of different sizes? For example:
enum class code {A,B,C};
enum class res {X1,X2,X3,X4,X5};
std::map<code, ?> name {
{code:A, {res::X1,res::X2}},
{code:B, {res::X2,res::X3, res::X4}},
{code:C, {res::X5}}
};
I need to find at compile time if res::X2 is in map name at code::B
This expression should, I think, check for that using static_assert:
constexpr bool validate(code t, res p, int i = 0) {
return (name[t][i] == p ? true : ((sizeof(name[t]) == (i+1)) ? false :validate(t, p, ++i)));
}
Because validate is a constexpr a basic array would work but how to define it in a map argument as an array of type res? And that each array could be different in size?
So, I've made a mistake. I was under the impression that map can be accessed in constexpr function. What container type can you suggest me that would allow me to achieve what I have written above?
If it is ok for the array to be const, this works:
std::map<code, std::initializer_list<res>> name {
{code::A, {res::X1,res::X2}},
{code::B, {res::X2,res::X3, res::X4}},
{code::C, {res::X5}}
};
If you need to be able to write to the array, you'll need something like this:
std::map<code, std::vector<res>> name {
{code::A, {res::X1,res::X2}},
{code::B, {res::X2,res::X3, res::X4}},
{code::C, {res::X5}}
};
This will come at the cost of additional memory allocations, since vector allocated on the heap.
If you want it to be writable and are ok with a fixed size, this also works and avoids the additional allocations:
std::map<code, std::array<res, 3>> name {
{code::A, {res::X1,res::X2}},
{code::B, {res::X2,res::X3, res::X4}},
{code::C, {res::X5}}
};
As for the second part of your question, I'm not quite sure if any solution will work, given that you cannot access a map in a constexpr function.
You can't use a std::map in a constexpr expression, not least because it has a non-trivial destructor (~map(); specified in the standard).
If you search the map section of the standard for constexpr, you won't find it (http://eel.is/c++draft/map), whereas you will for std::array (http://eel.is/c++draft/array.syn)
Since std::map can't be used in constexpr expression I was forced to find another solution and thanks to #kfsone and #H. Guijt for pointing that out as well as mentioning std::initializer_list and std::array which lead me to this solution.
Since the data in the map in the question will be constant, i can do without an associative container. So I used a sorted array of std::initializer_lists together with a constexpr implementation of find function which works great for my needs.
template <class It, class T>
inline constexpr It sfind (It begin, It end, T const& value) noexcept
{
return ! (begin != end && *begin != value)? begin : sfind (begin+1, end, value);
}
enum class code {A,B,C};
enum class res {X1,X2,X3,X4,X5};
constexpr std::array<std::initializer_list<res>, 3> name {{
{res::X1,res::X2}, //code::A
{res::X2,res::X3, res::X4}, //code::B
{res::X5} // code::C
}};
const code c = code::A;
const res r = res::X3;
static_assert (name[static_cast<int>(c)].end () - sfind(name[static_cast<int>(c)].begin(), name[static_cast<int>(c)].end(), r) != 0,"Not found");

How to construct a tuple from an array

I am designing a C++ library that reads a CSV file of reported data from some experiment and does some aggregation and outputs a pgfplots code. I want to make the library as generic and easy to use as possible. I also want to isolate it from the data types that are represented in the CSV file and leave the option to user to parse each column as she desires. I also want to avoid Boost Spirit Qi or other heavy duty parser.
The simple solution I have is for the user to create a type for each column, with a constructor that takes "char *". The constructor does its own parsing for the value it is given, which is one cell from the data. The user then passes me a list of types; the schema, representing the types in a line of data. I use this type list to create a tuple, in which every member of the tuple is responsible for parsing itself.
The problem now is how to initialise (construct) this tuple. Dealing with tuples is of course not straightforward since iterating over their elements is mostly a compile-time operation. I used Boost Fusion at first to achieve this task. However, the function I used (transform) although might take a tuple as input (with the appropriate adapter), it does not seem to return a tuple. I need the return value to be a tuple so some other code can use it as an associative type-to-value container (access it by type via std::get<T>), while using only standard tools, that is, without using Boost. So I had to convert whatever Fusion's transform returned into std::tuple.
My question is how to avoid this conversion, and better yet how to avoid Boost Fusion completely.
A simple solution that comes to mind is to use the constructor of std::tuple, and somehow pass each element its respective "const *" that it needs to construct. However, while this is possible using some complicated template-based enumeration techniques, I am wondering if there is a straightforward "parameter-pack"-like approach, or an even simpler way to pass the values to the constructors of the individual elements of a tuple.
To clarify what I am seeking, kindly take a look at this following code.
#include <cstdio>
#include <array>
template <typename...> struct format {};
template <typename...> struct file_loader {};
template <typename... Format>
struct
file_loader<format<Format...> > {
void load_file() {
size_t strsize = 500u;
char *str = new char[strsize]();
auto is = fopen("RESULT","r");
/* example of RESULT:
dataset2,0.1004,524288
dataset1,0.3253,4194304
*/
while(getline(&str, &strsize, is) >= 0) {
std::array<char*, 3> toks{};
auto s = str;
int i = 2;
while(i --> 0)
toks[i] = strsep (&s, ",");
toks[2] = strsep (&s, ",\n");
std::tuple<Format...> the_line{ /* toks */ } ; // <-- HERE
//// current solution:
// auto the_line{
// as_std_tuple( // <-- unnecessary conversion I'd like to avoid
// boost::fusion::transform(boost::fusion::zip(types, toks), boost::fusion::make_fused( CAST() ))
// )};
// do something with the_line
}
}
};
#include <string>
class double_type {
public:
double_type() {}
double_type(char const *token) { } // strtod
};
class int_type {
public:
int_type() {}
int_type(char const *token) { } // strtoul
};
int main(int argc, char *argv[]) {
file_loader< format< std::string,
double_type,
int_type > >
{}.load_file();
return 0;
}
I've highlighted the interesting line as "HERE" in a comment.
My question precisely is:
Is there a way to construct a std::tuple instance (of heterogeneous
types, each of which is implicitly convertible from "char *") with
automatic storage duration (on the stack) from a std::array<char *, N>,
where N equals the size of that tuple?
The answer I am seeking should
Avoid Boost Fusion
(Simplicity condition) Avoid using more than 5 lines of boilerplate template-based enumeration code
Alternatively, shows why this is not possible to do in the C++14 standard
The answer can use C++17 constructs, I wouldn't mind.
Thank you,
As with all questions involving std::tuple, use index_sequence to give you a parameter pack to index the array with:
template <class... Formats, size_t N, size_t... Is>
std::tuple<Formats...> as_tuple(std::array<char*, N> const& arr,
std::index_sequence<Is...>)
{
return std::make_tuple(Formats{arr[Is]}...);
}
template <class... Formats, size_t N,
class = std::enable_if_t<(N == sizeof...(Formats))>>
std::tuple<Formats...> as_tuple(std::array<char*, N> const& arr)
{
return as_tuple<Formats...>(arr, std::make_index_sequence<N>{});
}
Which you would use as:
std::tuple<Format...> the_line = as_tuple<Format...>(toks);

Removing potentially redundant template parameters when loading a binary file into Eigen matrix

I want to read a plain binary file containing a number of unsigned 16-bit integers into an Eigen matrix, and I wrote a templated utility to do this. This is what the caller looks like:
Matrix<uint16_t, Dynamic, Dynamic> data;
int retval = read_data<Matrix<uint16_t, Dynamic, Dynamic>, uint16_t>(
argv[1], data);
And here's what read_data looks like:
template <typename Derived, typename Scalar> // Per #Jarod42, get rid of Scalar here (*)
int read_data(const char* const fname, MatrixBase<Derived>& data) {
// (*) If we don't have Scalar as a template, just uncomment this:
// typedef typename Derived::Scalar Scalar;
ifstream fin(fname, ios::binary);
if (!fin) {
return 2;
}
fin.seekg(0, fin.end);
long long bytes = fin.tellg();
if (bytes % sizeof(Scalar) != 0) {
// The available number of bytes won't fill an even number of Scalar
// values
return 3;
}
long long nscalars = bytes / sizeof(Scalar);
// See http://forum.kde.org/viewtopic.php?f=74&t=107551
MatrixBase<Derived>& data_edit = const_cast<MatrixBase<Derived>&>(data);
data_edit.derived().resize(nscalars, 1);
Scalar* buffer = new Scalar[nscalars]; // Switched to vector per #Casey
fin.seekg(0, fin.beg);
fin.read(reinterpret_cast<char*>(buffer), bytes);
if (!fin) {
// All data not read. fin.gcount() will indicate bytes read.
return 4;
}
for (long long idx = 0; idx < nscalars; ++idx) {
data_edit(idx) = buffer[idx];
}
return 0;
}
In brief,
the file is opened,
its size is obtained,
an array is dynamically allocated to store all the data,
the file is read into the array,
the array's contents are copied into the matrix.
This is reasonable and it works (though I'm open to suggestions for improvements), but I think the function has one too many template parameters, and the function call in the caller is just too verbose. I think there should be a way to eliminate the second template parameter, which only serves to tell read_data the number of bytes per scalar (2 in the case of uint16_t), and which I believe should be inferrable using the first template parameter.
Questions Is there a way to eliminate the seemingly redundant second template parameter to read_data?
Also, is my approach of passing in a matrix reference only to resize it in the read_data function (using the verbose and confusing idiom of creating a modifiable reference to the matrix in order to resize it via derived()) the right way to proceed? I realize this dynamically allocates memory, which is fine, but I think it is not doing anything wasteful---correct?.
(Discussion Is there other improvements to this code one would like to see? I'm a C or Python numerical coder; in C, I'd just deal with void* arrays and pass an extra function argument telling the function the size of each scalar; with Python I'd just do numpy.fromfile('path/to/file.bin', dtype=numpy.uint16) and be done with it. But I'd like to do it right by Eigen and C++.)
NB. I use matrixes instead of vectors because I'll be resizing them into rectangular matrixes later.
NB2. In Fixed Sized Eigen types as parameters the notion of templating the function using the scalar type is promoted. I am not averse to this approach, I chose to pass read_data a matrix reference instead of making it return a Matrix object because I wanted integer return values indicating errors---though now I realize I ought to make those exceptions.
NB3. In c++ check for nested typedef of a template parameter to get its scalar base type an elaborate set of helper classes is used to, I think, achieve a similar effect for templated classes. I'm curious if a simpler approach can be used here, for a templated function.
NB4. A simple improvement that I'm aware of is typedeffing Matrix<uint16_t, Dynamic, Dynamic> to reduce verbosity.
I think that Matrix<uint16_t, Dynamic, Dynamic> should have a typedef to retrieve uint16_t. If so, you may write as first line (assuming it is type):
typedef typename Derived::type Scalar;
If there is no typedef, you may write a traits for that:
template <typename> struct matrix_type;
template <typename T, typename U1, typename U2>
struct matrix_type<Matrix<T, U1, U2> >
{
typedef T type;
typedef U1 type1;
typedef U2 type2;
};
And then write
typedef typename matrix_type<Derived>::type Scalar;
Note:
If you have written the parameters in the other order
template <typename Derived, typename Scalar>
int read_data(const char* const fname, MatrixBase<Derived>& data);
you may write (as the last parameter may be deduced):
Matrix<uint16_t, Dynamic, Dynamic> data;
int retval = read_data<uint16_t>(argv[1], data);
And now that the parameter is obsolete, you may write directly:
Matrix<uint16_t, Dynamic, Dynamic> data;
int retval = read_data(argv[1], data);
You may want to look at map in eigen. It takes a chuck a memory directly.
TutorialMapClass.html">http://eigen.tuxfamily.org/dox/group_TutorialMapClass.html
To construct a Map variable, you need two other pieces of information: a pointer to the region of memory defining the array of coefficients, and the desired shape of the matrix or vector. For example, to define a matrix of float with sizes determined at compile time, you might do the following:
Map mf(pf,rows,columns);

General iterable type with specific element type

I'm trying to write a function for enumerating through a number of a specific base, where the number is stored in some kind of list. Here is an example, taking a std::vector
void next_value(std::vector<unsigned int> &num, unsigned int base) {
unsigned int carry = 1;
for (unsigned int &n: num) {
n += carry;
if (n >= base) {
carry = 1;
n = 0;
} else {
carry = 0;
}
}
}
The num vector doesn't necessarily need to be a vector, it can be an array, or actually any type that has a std::begin() and std::end() defined for it. Is there a way to express that num can be anything with begin() and end(), but that it must have unsigned int type for its elements?
If you really want to check this, try:
template <class Sequence>
void next_value(Sequence &num, unsigned int base) {
static_assert(boost::is_same<Sequence::value_type, unsigned>::value, "foo");
// ...
If you're not using C++11 yet, use BOOST_STATIC_ASSERT instead.
If you need to support plain C-style arrays, a bit more work is needed.
On the other hand, #IgorTandetnik correctly points out that you probably do not need to explicitly check at all. The compiler will give you an (ugly) error if you pass a type which is truly unusable.
Writing a generic function with a static_assert is a good idea, because you can give the user a helpful error message rather than "foo".
However there is another approach using C++11:
template <typename Container, typename ValueType>
typename std::enable_if<std::is_same<Container::value_type, ValueType>::value, void>::type
next_value(Container& num, ValueType base)
{
// ...
}
This is a rather cryptic approach if you've never seen this before. This uses "Substitution failure is not an error" (SFINAE for short). If the ValueType doesn't match the Container::value_type, this template does not form a valid function definition and is therefore ignored. The compiler behaves as if there is not such function. I.e., the user can't use the function with an invalid combination of Container and ValueType.
Note that I do recommend using the static_assert! If you put a reasonable error message there, the user will thank you a thousand times.
I would not in your case.
Change carry to a book, use ++ instead of +=, make base a type T, and n an auto&.
Finally, return carry.
Your code now ducktypes exactly the requirements.
If you want diagnostics, static assert that the operations make sense with custom error messages.
This let's your code handle unsigned ints, polynomials, bigints, whatever.

C++ check if element is std::vector

i would like to iterate through a vector and check if elements are vectors or strings. Also i need a way to pass different vecors to a function.
Something like this:
using namespace std;
string toCustomString(<some vector> vec) {
string ret = "";
for(size_t i = 0; i < vec.length(); ++i)
if (vec[i] == %vector%)
ret += toCustomString(vec[i]);
else //if type of vec[i] is string
ret += "foo"+vec[i]+"bar";
}
return ret;
}
Well, first i need to know how i can check correctly if vec[i] is a std::vector
Then i need to know how to define the paramater for the function to accept any kind of (multidimensional) vector
std::vector can only contain one type - that is the T in std::vector<T>, which can be accessed with the member value_type.
What you probably are looking for is template specialization:
template<typename T>
string toCustomString(std::vector<T> vec) {
// general case
}
template<>
string toCustomString<std::string>(std::vector<std::string> vec) {
// strings
}
(if you want to partially specialize it over all vectors then you'll need to lift it to a struct)
If you really want to store both strings and vectors in the vector then look at Boost.Variant and Boost.Any
Generally, your <some vector> vec would have type either vector<string> or vector<vector<string>>, for example.
In order to declare the variable, you need its type, and its type also specifies exactly what it stores.
Now, you can work around this using Boost.Variant (or roll your own discriminated union), like so:
typedef boost::variant<std::string, std::vector<std::string>> Vec_of_StringOrVec;
but Dirk Holsopple is right that this isn't idiomatic C++, and you may be better off looking for a different approach.
As everyone says, vectors in C++ only hold one type. There's no need or point in checking the type of each element in turn, which is just as well because there's no way to do that. What you do instead is overload the function on the type of the argument. Something like this:
string toCustomString(const string &str) {
return "foo" +str + "bar";
}
template <typename T>
string toCustomString(const std::vector<T> &vec) {
string ret;
for(size_t i = 0; i < vec.size(); ++i)
ret += toCustomString(vec[i]);
return ret;
}
Now, if someone passes a vector<string> into toCustomString then the call toCustomString(vec[i]) will select the toCustomString(const string &str) overload.
If someone passes a vector<int> into toCustomString then the code won't compile, because there is (currently) no toCustomString(int) overload[*].
If someone passes a vector<vector<string>> to toCustomString then toCustomString(vec[i]) will pass a vector<string>, see above.
In all three cases, different toCustomString functions are called. In the first case it's toCustomString<string>(const vector<string>&), which is a different instantiation of the toCustomString template from the third case, toCustomString<vector<string>>(const vector<vector<string>>&). The middle case tries to instantiate toCustomString<int>, but fails because toCustomString(v[i]) doesn't match any function it knows about.
All of this is determined at compile time. The point of templates is to create multiple functions (or classes) with particular differences between them. In this case the difference is the type of vector passed in.
[*] This seems in line with your claim that vec[i] must be either a vector or a string, not any third option. If you wanted for example the return value for a vector<something_else> to be empty, then you could add a catch-all template:
template <typename T>
string toCustomString(const T &) {
return string();
}
and of course you can add more overloads for any other types you want to handle.