overloading operator == for pods - c++

I am working on some low level code with high level interfaces and felt need for comparisons operator for unit testing for plain old data types(like FILETIME struct) but since C++ doesn't even provide memberwise comparisons, so I wrote this:
template <typename Type>
std::enable_if_t<std::is_pod<Type>::value, bool> operator==(const Type& a,
const Type& b) {
return std::memcmp(&a, &b, sizeof(Type)) == 0;
}
So my question is, is this a good way or there are some hidden demons which will give me trouble later down the development cycle but it's kinda working for now.

Is C++14 available? If so, consider PFR library, which makes structures into tuples

This question is a restricted variant of Define generic comparison operator, as noted in the comments. An example of the dangers and effects of padding on the proposed operator== for POD is:
template <typename Type>
std::enable_if_t<std::is_pod<Type>::value, bool> operator==(const Type& a,
const Type& b)
{
return std::memcmp(&a, &b, sizeof(Type)) == 0;
}
struct St {
bool a_bool;
int an_int;
};
union Un {
char buff[sizeof(St)];
St st;
};
std::ostream &operator<<(std::ostream & out, const St& data)
{
return out << '{' << std::boolalpha << data.a_bool << ", " << data.an_int << '}';
}
int main()
{
Un un{{1,2,3,4,5}};
new (&un.st) St;
un.st.a_bool = true;
un.st.an_int = 5;
St x={true, 5};
std::cout << "un.a=" << un.st << '\n';
std::cout << "x=" << x << '\n';
std::cout << (x == un.st) << "\n";
return 0;
}
Both un.st and x contain the same data, but un.st contains some garbage in the padded bytes. The padded garbage makes the propose operator== return false for logically equivalent objects. Here is the output I have got for both gcc (head-9.0.0) and clang (head-8.0.0):
un.a={true, 5}
x={true, 5}
false
Update: this happens also with regular new/delete, as run on wandbox.org:
std::enable_if_t<std::is_pod<Type>::value, bool> operator==(const Type& a,
const Type& b)
{
return std::memcmp(&a, &b, sizeof(Type)) == 0;
}
struct St {
bool a_bool;
int an_int;
};
std::ostream &operator<<(std::ostream & out, const St& data)
{
return out << '{' << std::boolalpha << data.a_bool << ", " << data.an_int << '}';
}
static constexpr unsigned N_ELEMENTS = 2;
int main()
{
{
volatile char * arr = new char[sizeof(St) * N_ELEMENTS];
for (unsigned i=0; i < sizeof(St) * N_ELEMENTS ; ++i)
arr[i] = i + 1;
std::cout << "arr = " << (void*)arr << "\n";
delete[] arr;
}
St * ptr_st = new St[N_ELEMENTS];
std::cout << "ptr_st = " << ptr_st << "\n";
for (unsigned i=0 ; i != N_ELEMENTS; ++i) {
ptr_st[i].a_bool = true;
ptr_st[i].an_int = 5;
}
St x={true, 5};
std::cout << "x=" << x << '\n';
std::cout << "ptr_st[1]=" << ptr_st[1] << '\n';
std::cout << (x == ptr_st[1]) << "\n";
return 0;
}
For which the output is:
arr = 0x196dda0
ptr_st = 0x196dda0
x={true, 5}
ptr_st[1]={true, 5}
false

Related

Homework task: Checking the equality of two arrays

I am stuck on a homework question which requires me to create/modify a function which will set two arrays equal to each other. The question asks:
"Use the copy assignment (=) operator to set the two arrays equal to each other, this can be checked with the following:
y = x;
cout << "x equals y? " << (x == y) << endl; //Should return "True"
And is set within the following rules:
"Note that two Array objects should be considered equal only if they have the same length and the same element values."
This is the code I have, I have implemented two debugging sections which shows that they are indeed equal both in the assignment function and the main function, so my best guess is that the lengths don't match up. I am not allowed to modify any of the code which was provided (All the class and function stuff, or anything above the debugger in main), so I'm not sure how to set the lengths equal to each other in order to satisfy the condition (x==y)
#include <iostream>
using namespace std;
// definition
#define MAX_LENGTH 100
#define INIT_VALUE 0
class Array {
public:
Array(int length);
Array& operator=(const Array& other);
int length() const;
int& operator[](int index);
bool operator==(const Array& other) const;
bool operator!=(const Array& other) const;
private:
int length_;
int elements_[MAX_LENGTH];
};
// implementation
Array::Array(int length) {
length_ = length;
if (length_ > MAX_LENGTH) length_ = MAX_LENGTH;
for (int i = 0; i < length_; ++i) {
elements_[i] = INIT_VALUE;
}
}
Array& Array::operator=(const Array& other)
{
/*DEBUG*/cout << endl << endl << "<<NOW IN ASSIGNMENT FUNCTION>>" << endl << endl;
for (int i = 0; i < other.length_; ++i)
{
elements_[i] = other.elements_[i];
/*DEBUG*/cout << endl << "Elements: " << elements_[i] << " | Other Elements: " << other.elements_[i] << endl;
}
return *this;
}
int Array::length() const {
return length_;
}
int& Array::operator[](int index) {
// Q3 code goes here
return elements_[index];
}
bool Array::operator==(const Array& other) const
{
if (length_ != other.length_) return false;
for (int i = 0; i < other.length_; ++i) {
if (elements_[i] != other.elements_[i]) return false;
}
return true;
}
bool Array::operator!=(const Array& other) const
{
if (length_ != other.length_)
{
return true;
}
for (int j = 0; j < other.length_; ++j)
{
if (elements_[j] != other.elements_[j]) return true;
}
return false;
}
// testing
int main()
{
Array x(10);
x[3] = 42;
cout << "x contains ";
for (int i = 0; i < x.length(); ++i) {
cout << x[i] << " ";
}
cout << endl;
Array y(5);
cout << boolalpha;
cout << "x equals y? " << (x == y) << endl;
cout << "x notequals y? " << (x != y) << endl;
y = x;
//DEBUG SECTION
cout << endl << endl << "<<NOW IN MAIN>>" << endl << endl;
for (int i = 0; i < x.length(); ++i)
{
cout << endl << "Elements: " << x[i] << " | Other Elements: " << y[i] << endl;
}
//END OF DEBUG SECTION
cout << "x equals y? " << (x == y) << endl;
}
So the question is, how can I get these arrays to have the same length without modifying them in 'main'? Can I do this through the assignment function?
You just forgot to assign the same length in the the Array::operator=.
This can be done by writing this->length_ = other.length_; in the
Array& Array::operator=(const Array& other) before overwriting the array.
As mentioned before, you did not asign the length correctly in the = operator.
Fix like this:
Array& Array::operator=(const Array& other)
{
length_ = other.length_;
for (int i = 0; i < length_; ++i)
{
elements_[i] = other.elements_[i];
}
return *this;
}
Also you can simplify your != operator drastically
bool Array::operator!=(const Array& other) const
{
return !(*this == other);
}
However, in my opinon even more important, you should also make use of the std-containers which allow dynamic sizes such as std::vector. This also would have avoided your bug.
In my opinion you should use these std-containers as soon as possible and get used to them. They are almost always the right choice when in doubt.
With std::vector your program could look like this:
#include <iostream>
#include <vector>
using namespace std;
// definition
#define INIT_VALUE 0
class Array {
public:
Array(int length);
Array& operator=(const Array& other);
int length() const;
int& operator[](int index);
bool operator==(const Array& other) const;
bool operator!=(const Array& other) const;
private:
std::vector<int> elements_;
};
// implementation
Array::Array(int length)
:
elements_(length, INIT_VALUE)
{
}
Array& Array::operator=(const Array& other)
{
/*DEBUG*/cout << endl << endl << "<<NOW IN ASSIGNMENT FUNCTION>>" << endl << endl;
elements_ = other.elements_;
return *this;
}
int Array::length() const {
return static_cast<int>(elements_.size());
}
int& Array::operator[](int index) {
// Q3 code goes here
return elements_[index];
}
bool Array::operator==(const Array& other) const
{
return elements_ == other.elements_;
}
bool Array::operator!=(const Array& other) const
{
return !(*this == other);
}
// testing
int main()
{
Array x(10);
x[3] = 42;
cout << "x contains ";
for (int i = 0; i < x.length(); ++i) {
cout << x[i] << " ";
}
cout << endl;
Array y(5);
cout << boolalpha;
cout << "x equals y? " << (x == y) << endl;
cout << "x notequals y? " << (x != y) << endl;
y = x;
//DEBUG SECTION
cout << endl << endl << "<<NOW IN MAIN>>" << endl << endl;
for (int i = 0; i < x.length(); ++i)
{
cout << endl << "Elements: " << x[i] << " | Other Elements: " << y[i] << endl;
}
//END OF DEBUG SECTION
cout << "x equals y? " << (x == y) << endl;
}

std::setw for the whole operator<< of user-defined type

We know, that the std::setw() influence only on the next output.
So, what standard practice to align
the whole operator<< of user-defined type in table output:
class A
{
int i, j;
public:
friend ostream& opeartor<<(ostream& out, const A& a) {
return << "Data: [" << i << ", " << j << "]";
}
}
// ...
A[] as;
out << std::left;
for (unsigned i = 0; i < n; ++i)
out << std::setw(4) << i
<< std::setw(20) << as[i] // !!!
<< std::setw(20) << some_strings[i]
<< some_other_classes[i] << std::endl;
out << std::right;
Just add a setw() method to your class:
class A
{
int i, j;
mutable int width = -1;
public:
A& setw(int n) {
this->width = n;
return *this;
}
friend ostream& operator<<(ostream& out, const A& a);
};
And when you print it, if you want to align, simply use it:
int main() {
A as[5];
for (auto & a : as)
cout << a.setw(15) << endl;
}

Operator Overloading solution

i have made a c++ code. An MList that holds items in it. I overloaded the << operator to print the values in MList in a particular format. Here is the code:
friend ostream& operator<<(ostream &out, const MSet<V> &m)
{
string s = "";
s += "Size " + to_string(m.size_) + "\n";//out << m.size() << endl;
s += "Cap " + to_string(m.capacity_) + "\n"; //out << m.capacity() << endl;
for (int i = 0; i < m.size_; i++)
{
if (i < m.size_ - 1)
s += m.ary[i].element + ",";//out << m.ary[i].element << ",";
else
s += m.ary[i].element;
}
//cout << "String : " << s;
return out << s;
}
But it does not print correct value. It prints the size and capacity right but not the values. Instead of values, it prints some signs like heart:
You can see it prints size and capacity right but not the values. Here is the relevant code. I am executing case 2 only right now:
#include<iostream>
using std::cout; using std::endl;
using std::ostream; using std::cin; using std::boolalpha;
#include<string>
using std::string;
using namespace std;
template <class V>
struct SetElement
{
V element;
int cnt;
SetElement() = default;
SetElement(V v) : element(v){}
};
template <class V>
ostream &operator<<(ostream & o,const SetElement<V> &p)
{
return o << p.element;
}
template <class V>
class MSet
{
private:
SetElement<V> *ary;
size_t capacity_;
size_t size_;
public:
MSet(V val)
{
capacity_ = 2;
ary = new SetElement<V>[capacity_];
ary[0].element = val;
ary[0].cnt = 1;
size_ = 1;
}
SetElement<V>* find(V val)
{
SetElement<V> *found = nullptr;
bool yes = false;
for (int i = 0; i < size_ && !yes; i++)
{
if (ary[i].element == val)
{
found = &ary[i];
yes = true;
}
}
return found;
}
friend ostream& operator<<(ostream &out, const MSet<V> &m)
{
string s = "";
s += "Size " + to_string(m.size_) + "\n";//out << m.size() << endl;
s += "Cap " + to_string(m.capacity_) + "\n"; //out << m.capacity() << endl;
for (int i = 0; i < m.size_; i++)
{
if (i < m.size_ - 1)
s += m.ary[i].element + ",";//out << m.ary[i].element << ",";
else
s += m.ary[i].element;
}
//cout << "String : " << s;
return out << s;
}
};
int main(){
int test;
long l1, l2, l3;
cin >> test;
cout << boolalpha;
switch (test){
// ...
case 2: {
cin >> l1 >> l2;
MSet<long> m_l(l1);
auto p = m_l.find(l1);
if (p != nullptr)
cout << *p << endl;
else
cout << "Val:" << l1 << " not found " << endl;
p = m_l.find(l2);
if (p != nullptr)
cout << *p << endl;
else
cout << "Val:" << l2 << " not found " << endl;
//cout << "MList \n";
cout << m_l;
break;
}
// ...
}
}
You're adding the values into a temporary string, which may involve implicit conversions depending of the template type (here your numerical values were converted into characters).
Just print the values, without the temporary string:
friend ostream& operator<<(ostream &out, const MSet<V> &m)
{
out << "Size " << m.size_ << endl;
out << "Cap " << m.capacity_ << endl;
for (int i = 0; i < m.size_; i++)
{
if (i < m.size_ - 1)
out << m.ary[i].element << ",";
else
out << m.ary[i].element;
}
return out;
}

C++ Cycle through the addresses of an object

Objects (that are not dynamic) are blocks of data in memory.
Is there a way to cycle through and print each item in an object?
I tried doing it with 'this' but I keep getting errors.
#include "stdafx.h"
#include <iostream>
#include "TestProject.h"
using namespace std;
class myclass {
int someint = 10;
double somedouble = 80000;
int somearray[5] = {0, 1, 2, 3, 4};
public:
void somefunction();
};
void myclass::somefunction() {
cout << "\n test \n" << this;
myclass *somepointer;
somepointer = this;
somepointer += 1;
cout << "\n test2 \n" << *somepointer;
//Error: no opperator '<<' matches these operands
}
int main() {
myclass myobject;
myobject.somefunction();
return 0;
}
I'm guessing the error is because the types don't match. But I can't really figure a solution. Is there a dynamic type, or do I have to test the type somehow?
You must add friend global std::ostream operator << to display content of object
#include "stdafx.h"
#include <iostream>
using namespace std;
class myclass {
int someint;
double somedouble;
int somearray[5];
public:
myclass()
{
someint = 10;
somedouble = 80000;
somearray[0] = 0;
somearray[1] = 1;
somearray[2] = 2;
somearray[3] = 3;
somearray[4] = 4;
}
void somefunction();
friend std::ostream& operator << (std::ostream& lhs, const myclass& rhs);
};
std::ostream& operator << (std::ostream& lhs, const myclass& rhs)
{
lhs << "someint: " << rhs.someint << std::endl
<< "somedouble: " << rhs.somedouble << std::endl
<< "somearray: { ";
for (int iIndex = 0; iIndex < 5; iIndex++)
{
if (iIndex == 4)
lhs << rhs.somearray[iIndex] << " }" << std::endl;
else
lhs << rhs.somearray[iIndex] << ", ";
}
return lhs;
}
void myclass::somefunction() {
cout << "\n test \n" << this;
myclass *somepointer;
somepointer = this;
somepointer += 1; // wrong pointer to object with `object + sizeof(object)` address,
// data probably has been corrupted
cout << "\n test2 \n" << *somepointer; // displaying objects content
}
int main() {
myclass myobject;
myobject.somefunction();
return 0;
}
as you want to get to the object member using its pointers shifts I post another program
#include "stdafx.h"
#include <iostream>
using namespace std;
#pragma pack (push, 1) // force data alignment to 1 byte
class myclass {
int someint;
double somedouble;
int somearray[5];
public:
myclass()
{
someint = 10;
somedouble = 80000;
somearray[0] = 0;
somearray[1] = 1;
somearray[2] = 2;
somearray[3] = 3;
somearray[4] = 4;
}
void somefunction();
friend std::ostream& operator << (std::ostream& lhs, const myclass& rhs);
};
#pragma pack (pop) // restore data alignment
std::ostream& operator << (std::ostream& lhs, const myclass& rhs)
{
lhs << "someint: " << rhs.someint << std::endl
<< "somedouble: " << rhs.somedouble << std::endl
<< "somearray: { ";
for (int iIndex = 0; iIndex < 5; iIndex++)
{
if (iIndex == 4)
lhs << rhs.somearray[iIndex] << " }" << std::endl;
else
lhs << rhs.somearray[iIndex] << ", ";
}
return lhs;
}
void myclass::somefunction() {
int* pSomeInt = (int*)this; // get someint address
double *pSomeDouble = (double*)(pSomeInt + 1); // get somedouble address
int* pSomeArray = (int*)(pSomeDouble + 1); // get somearray address
std::cout << "someint: " << *pSomeInt << std::endl
<< "somedouble: " << *pSomeDouble << std::endl
<< "somearray: { ";
for (int iIndex = 0; iIndex < 5; iIndex++)
{
if (iIndex == 4)
std::cout << pSomeArray[iIndex] << " }" << std::endl;
else
std::cout << pSomeArray[iIndex] << ", ";
}
}
int main() {
myclass myobject;
myobject.somefunction();
return 0;
}
C++, by design, has no reflection feature. This means there is no generic, type-independent way to acces type metadata (e.g. the list of members if a class and their types) at runtime. So what you're trying to do (if I understand it correctly) cannot be done in C++.
Also I'm not sure what you meant by "objects (that are not dynamic)". all objects are blocks of data in memory, regardless of whether they are dynamically allocated or not.

Convert vector<string> to other types

I've a class withmap<string,vector<string>>.
I want to give a user a member function to receive the value for a key in different formats than std::vector(string):
vector(string),
string,
vector(int),
vector(float) and
bool
example:
bool x = (bool) myClass["dummy_boolean_type"]
x = myClass["dummy_boolean_type"].as<bool>
int y = (int) myClass["dummy_boolean_type"]
Can someone have an example what is the best way to achieve it ?
(without a use in Boost)
You cannot provide your class with any member function or functions
that will support the two constructions you want:
T x = myClassInstance["key"].as<T> // (1)
T x = (T) myClassInstance["key"] // (2)
In the case of (1), the immediate reason is simply that the construction is
not legal C++. So let's suppose it is replaced by:
T x = myClassInstance["key"].as<T>() // (1a)
But this doesn't help, and the reason is the same for both (1a) and (2):
The expression myClassInstance["key"] will have to evaluate to some object e or reference to such that is returned by:
myClass::operator[](std::string const &);
This e is the vector<string> to which key maps in your
map<string,vector<string> data member of myClass. It is not myClassInstance.
So what you are asking for are member functions of myClass that will support
the constructions:
T x = e.as<T> // (1b)
T x = (T) e // (2b)
where e is an std::vector<std::string>.
Clearly, nothing you can do in myClass can address your requirement. In
(1b) and (2b), myClass is nowhere to be seen.
Is there any template member function of std::vector<std::string>:
template<typename T>
T as() const;
that has the behaviour you want for (1b)?
Does std::vector<std::string> have any template member function:
template<typename T>
operator T() const;
that has the behaviour you want for (2b)?
No and No.
However...
You can implement an as template member function of myClass that
supports conversions such as you mention. Its signature - of course -
would be:
template<typename T>
T myClass::as(std::string const & key) const;
and you would invoke it like:
T x = myClassInstance.as<T>("key") // (1c)
I'll sketch an implemention that assumes we're content with the
conversions from std::vector<std::string> to:
std::string
std::vector<int>
bool
which will be enough to get you under way.
To convert an std::vector<std::string> vs to std::string I'll concatenate
the elements of vs.
To convert an std::vector<std::string> vs to std::vector<int> I'll convert each element of vs from a decimal numeral, if I can, to the
integer the numeral represents, and return a vector of those integers. Without
prejudice to other policies I'll throw an std::invalid_argument exception
when an element doesn't trim to a decimal numeral.
I am spoilt for choice as to what you might mean by converting an std::vector<std::string>
to bool, so I will arbitrarily say that vs is true if I can convert it
to a vector<int> of which any element is non-0 and is false if I can convert
it to a vector<int> in which all elements are 0.
The sketch:
#include <type_traits>
#include <map>
#include <vector>
#include <string>
#include <algorithm>
namespace detail {
template<typename T>
struct convert_to
{
static T from(std::vector<std::string> const & vs) {
static constexpr bool always_false = !std::is_same<T,T>::value;
static_assert(always_false,
"Calling `convert_to<T>::from` for unimplemented `T`");
return *(T*)nullptr;
}
};
template<>
std::string convert_to<std::string>::from(std::vector<std::string> const & vs)
{
std::string s;
for ( auto const & e : vs ) {
s += e;
}
return s;
}
template<>
std::vector<int>
convert_to<std::vector<int>>::from(std::vector<std::string> const & vs)
{
auto lamb = [](std::string const & s) {
std::size_t lastoff = s.find_last_not_of(" \t\f\v\n\r");
int i;
try {
std::size_t nlen;
i = std::stoi(s,&nlen);
if (nlen <= lastoff) {
throw std::invalid_argument("");
}
}
catch(std::invalid_argument const & e) {
throw std::invalid_argument(
"Cannot convert \"" + s + "\" to int");
}
return i;
};
std::vector<int> vi;
std::transform(vs.begin(),vs.end(),std::back_inserter(vi),lamb);
return vi;
}
template<>
bool convert_to<bool>::from(std::vector<std::string> const & vs)
{
auto vi = convert_to<std::vector<int>>::from(vs);
for (auto const & i : vi) {
if (i) {
return true;
}
}
return false;
}
} // namespace detail
struct myClass // Your class
{
// Whatever...
std::vector<std::string> & operator[](std::string const & key) {
return _map[key];
}
template<typename T>
T as(std::string const & key) {
return detail::convert_to<T>::from(_map[key]);
}
// Whatever...
private:
std::map<std::string,std::vector<std::string>> _map;
};
The one take-away point here is the use of template<typename T>
detail::struct convert_to, with its solitary static member function:
T from(std::vector<std::string> const & vs)
which in the default instantiation will provoke a static_assert failure
reporting that no conversion to T from std::vector<std::string> has been
defined.
Then, for each type U to which you want a conversion, you have just to
write a specializing definition:
template<>
U convert_to<U>::from(std::vector<std::string> const & vs);
as you see fit, and the construction (1c) will use it as per:
template<typename T>
T myClass::as(std::string const & key) {
return detail::convert_to<T>::from(_map[key]);
}
Here's an illustrative progam you can append to the sketch:
#include <iostream>
using namespace std;
template<typename T>
static void print_vec(std::vector<T> const & v)
{
cout << "{ ";
for (auto const & e : v) {
cout << e << " ";
}
cout << "}\n";
}
static void print_vec(std::vector<std::string> const & v)
{
cout << "{ ";
for (auto const & e : v) {
cout << '\"' << e << "\" ";
}
cout << "}\n";
}
int main()
{
myClass f;
f["int_vec"] = vector<string>{"0","1 "," 2"};
cout << "f[\"int_vec\"] = "; print_vec(f["int_vec"]);
f["true_vec"] = vector<string>{"0"," 1 ","0"};
cout << "f[\"true_vec\"] = "; print_vec(f["true_vec"]);
f["false_vec"] = vector<string>{"0"," 0","0 "};
cout << "f[\"false_vec\"] = "; print_vec(f["false_vec"]);
f["not_int_vec0"] = vector<string>{"0","1","2",""};
cout << "f[\"not_int_vec0\"] = "; print_vec(f["not_int_vec0"]);
f["not_int_vec1"] = vector<string>{"0","#","2",};
cout << "f[\"not_int_vec1\"] = "; print_vec(f["not_int_vec1"]);
f["not_int_vec2"] = vector<string>{"0"," 1$","2",};
cout << "f[\"not_int_vec2\"] = "; print_vec(f["not_int_vec2"]);
cout << "f.as<string>(\"int_vec\") = \""
<< f.as<string>("int_vec") << '\"' << endl;
cout << "f.as<string>(\"true_vec\") = \""
<< f.as<string>("true_vec") << '\"' << endl;
cout << "f.as<string>(\"false_vec\") = \""
<< f.as<string>("false_vec") << '\"' << endl;
cout << "f.as<string>(\"not_int_vec0\") = \""
<< f.as<string>("not_int_vec0") << '\"' << endl;
cout << "f.as<string>(\"not_int_vec1\") = \""
<< f.as<string>("not_int_vec1") << '\"' << endl;
cout << "f.as<string>(\"not_int_vec2\") = \""
<< f.as<string>("not_int_vec2") << '\"' << endl;
vector<int> va = f.as<vector<int>>("int_vec");
cout << "f.as<vector<int>>(\"int_vec\") = ";
print_vec(f.as<vector<int>>("int_vec"));
cout << boolalpha << "f.as<bool>(\"true_vec\") = "
<< f.as<bool>("true_vec") << endl;
cout << boolalpha << "f.as<bool>(\"false_vec\") = "
<< f.as<bool>("false_vec") << endl;
try {
cout << "f.as<vector<int>>(\"not_int_vec0\")...";
auto b = f.as<vector<int>>("not_int_vec0");
(void)b;
}
catch(std::invalid_argument const & e) {
cout << e.what() << endl;
}
try {
cout << "f.as<vector<int>>(\"not_int_vec1\")...";
auto b = f.as<vector<int>>("not_int_vec1");
(void)b;
}
catch(std::invalid_argument const & e) {
cout << e.what() << endl;
}
try {
cout << "f.as<vector<int>>(\"not_int_vec2\")...";
auto b = f.as<vector<int>>("not_int_vec2");
(void)b;
}
catch(std::invalid_argument const & e) {
cout << e.what() << endl;
}
// char ch = f.as<char>("int_vec"); <- static_assert fails
return 0;
}
It outputs:
f["int_vec"] = { "0" "1 " " 2" }
f["true_vec"] = { "0" " 1 " "0" }
f["false_vec"] = { "0" " 0" "0 " }
f["not_int_vec0"] = { "0" "1" "2" "" }
f["not_int_vec1"] = { "0" "#" "2" }
f["not_int_vec2"] = { "0" " 1$" "2" }
f.as<string>("int_vec") = "01 2"
f.as<string>("true_vec") = "0 1 0"
f.as<string>("false_vec") = "0 00 "
f.as<string>("not_int_vec0") = "012"
f.as<string>("not_int_vec1") = "0#2"
f.as<string>("not_int_vec2") = "0 1$2"
f.as<vector<int>>("int_vec") = { 0 1 2 }
f.as<bool>("true_vec") = true
f.as<bool>("false_vec") = false
f.as<vector<int>>("not_int_vec0")...Cannot convert "" to int
f.as<vector<int>>("not_int_vec1")...Cannot convert "#" to int
f.as<vector<int>>("not_int_vec2")...Cannot convert " 1$" to int
(gcc 5.1, clang 3.6, C++11)