Is it possible to declare methods via template in c++? - c++

My intention is to refrain from macros style when I need to define a lot of similar methods. So I'm interested, can I use templates or anything like that?
This is the general idea in pseudo-c++:
template <class T, class U> void myMethod(T t, U u){ ..do a lot .. }
class A {
public:
A(){}
void myMethod<int, int>;
void myMethod<float, char>;
// ... etc
};

template <class T, class U> class A
{
public:
void MemberSet( T t, U u );
};
ADDED:
#include <typeinfo>
#include <iostream>
using namespace std;
class A
{
public:
template <class T, class U> void MemberSet( T t, U u ) {
cout << typeid(t).name() << " " << typeid(u).name() << endl;
};
};
int main()
{
A a;
a.MemberSet(5,5);
a.MemberSet<char, long>(5,5);
}
you may want to explicitly instantiate
template void A::MemberSet<int, long> (int, long);

No, but you can use inheritance.
template <class derived_T, class T, class U>
struct base {
void myMethod_(T t, U u) {
// use this to access derived class members:
static_cast<derived_T*>(this)->
}
};
struct a : base<a, int, int>, base<a, float, float> {
template <class T, class U>
void myMethod(T&& t, U&& u) {
base<a,T,U>::myMethod_(std::forward<T>(t), std::forward<U>(u));
}
};

No, but you can:
template <class T, class U> void struct myMethodWrapper
{
void myMethod(T t, U u){ ..do a lot .. }
};
And then:
class A : public myMethodWrapper<int, int>,
public myMethodWrapper<float, float>
{
};
That behaves similarly.

Another option is to put the template code outside the class and call it from class methods.
#include <iostream>
using namespace std;
namespace myTemplates
{
// template method 'mult(a,b)'
// returns a*b
template <class T1, class T2>
T1 mult(T1 a, T2 b)
{
T1 result = a * b;
return result;
}
// template specialization 'mult(string aString, int m)'
// returns a string repeated m times
template <>
string mult<string, int>(string input, int m)
{
string result;
for (int i = 0; i < m; i++)
{
result += input;
}
return result;
}
}
class A {
public:
A(){}
int mult(int a , int b ) { return myTemplates::mult(a, b ) ; }
float mult(float a , float b ) { return myTemplates::mult(a, b ) ; }
string mult(string a , int b ) { return myTemplates::mult(a, b ) ; }
};
int main(void)
{
int iA = 2;
int iB = 3;
int iC = 0; // result
float fA = 20.1;
float fB = 30.3;
float fC = 0.0; // result
string sA = " -blah- ";
string sC; // result
iC = myTemplates::mult(iA,iB);
cout << "mult(" << iA << ", " << iB << ") = " << iC << endl;
fC = myTemplates::mult(fA,fB);
cout << "mult(" << fA << ", " << fB << ") = " << fC << endl;
sC = myTemplates::mult(sA,iB);
cout << "mult(" << sA << ", " << iB << ") = " << sC << endl;
A a;
iC = a.mult(iA,iB);
cout << "a.mult(" << iA << ", " << iB << ") = " << iC << endl;
fC = a.mult(fA,fB);
cout << "a.mult(" << fA << ", " << fB << ") = " << fC << endl;
sC = a.mult(sA,iB);
cout << "a.mult(" << sA << ", " << iB << ") = " << sC << endl;
return 1;
}
output:
mult(2, 3) = 6
mult(20.1, 30.3) = 609.03
mult( -blah- , 3) = -blah- -blah- -blah-
a.mult(2, 3) = 6
a.mult(20.1, 30.3) = 609.03
a.mult( -blah- , 3) = -blah- -blah- -blah-

Related

Elegant way to use std::get to access data in std::variant

I'm a new C++ user from the Java world. Here is the context: Different class needs to implement foo() function from Base class. But this function has different combination of my_type as input. I'm feeling using something like std::get<2>(input[1]) everywhere in the code is not easy to read and understand. Is there a elegant way to access content in an std::variant? Demo https://shorturl.at/tLQV3
#include <iostream>
#include <variant>
#include <vector>
using my_type = std::variant<int, float, bool>;
struct Base {
virtual void foo(std::vector<my_type>) = 0;
virtual ~Base() {};
};
struct B : Base {
static constexpr int kMetricRawDataTypes[] = {2,2,2,2};
void foo(std::vector<my_type> input) {
bool num_0 = std::get<2>(input[0]); // Question1.1 - is there any more elegant way to access the value?
bool num_1 = std::get<2>(input[1]);
bool num_2 = std::get<2>(input[2]);
bool num_3 = std::get<2>(input[3]);
std::cout << "input " << num_0 << " " << num_1 << " " << num_2 << " " << num_3 << std::endl;
}
};
struct A : Base {
static constexpr int kMetricRawDataTypes[] = {1, 2, 0, 1};
void foo(std::vector<my_type> input) {
float num_0 = std::get<1>(input[0]); // Question 1.2 - is there any more elegant way to access the value?
bool num_1 = std::get<2>(input[1]);
int num_2 = std::get<0>(input[2]);
float num_3 = std::get<1>(input[3]);
std::cout << "input " << num_0 << " " << num_1 << " " << num_2 << " " << num_3 << std::endl;
}
};
int main() {
my_type num1 = 1.0f;
my_type num2 = true;
my_type num3 = 5;
my_type num4 = 3.0f;
std::vector<my_type> input = {num1, num2, num3, num4};
A a;
a.foo(input);
return 0;
}
I feel there should be good solution using template. Please advise!
I'd use the validate function in my old answer as input and rewrite it slightly to fit your new class definition. Then to print the contained types, you could fold over operator,. To only have to implement foo once, you could put that in a CRTP base for A and B. I've chosen to make the validate function a member of the CRTP base here.
#include <iostream>
#include <variant>
#include <vector>
using my_type = std::variant<int, float, bool>;
struct Base {
virtual ~Base() = default;
virtual void foo(const std::vector<my_type>& input) const = 0;
};
template<class T> // A CRTP base for A and B
struct foo_impl : Base {
bool validate(const std::vector<my_type>& input) const {
return input.size() == std::size(T::kMetricRawDataTypes)
&& [&]<std::size_t... Is>(std::index_sequence<Is...>) {
// fold over && :
return (... && (input[Is].index() ==
T::kMetricRawDataTypes[Is]));
}(std::make_index_sequence<std::size(T::kMetricRawDataTypes)>());
}
void foo(const std::vector<my_type>& input) const override {
if(validate(input)) {
std::cout << "input";
[&]<std::size_t... Is>(std::index_sequence<Is...>) {
// fold over , (comma) to print:
((std::cout << ' ' <<
std::get<T::kMetricRawDataTypes[Is]>(input[Is])),
...);
}(std::make_index_sequence<std::size(T::kMetricRawDataTypes)>());
std::cout << '\n';
} else {
std::cout << "not valid\n";
}
}
};
struct A : foo_impl<A> { // inherit with `A` as a template parameter
static constexpr int kMetricRawDataTypes[] = {1, 2, 0, 1};
};
struct B : foo_impl<B> { // inherit with `B` as a template parameter
static constexpr int kMetricRawDataTypes[] = {2, 2, 2, 2};
};
Demo

Store generic callback in a map

i would like create a map of id / generic callback but I don't know if it's feasible. My idea is like this:
Different king od object
class Class1
{
public:
bool run(const int &temp){
std::cout << "worker1:" << temp << std::endl;
return 0;
}
};
class Class2
{
public:
bool run(const std::string &temp){
std::cout << "worker2:" << temp << std::endl;
return 0;
}
};
The template for the Callback object:
template <typename ReturnType, typename... Args>
class Callback
{
private:
std::function<ReturnType> _function;
public:
Callback(std::function < ReturnType(Args...)> function)
: _function(function){}
auto run(Args... args)
{
return function(std::forward<Args>(args)...);
}
};
an example of use
int main() {
Class1 class1;
Class2 class2;
std::map<int, Callback> cbs;
cbs[1] = std::bind(&Class1::run, &class1, std::placeholders::_1));
cbs[2] = std::bind(&Class1::run, &class1, std::placeholders::_1));
cbs[1].run(1);
cbs[2].run("string msg");
}
Maybe you can implement something with std::any
I created factory where I stored functions with any signature in a map.
Please have a look, if it could give your an idea. Otherwise I will delete this answer
#include <iostream>
#include <map>
#include <utility>
#include <any>
// Some demo classes ----------------------------------------------------------------------------------
struct Base {
Base(int d) : data(d) {};
virtual ~Base() { std::cout << "Destructor Base\n"; }
virtual void print() { std::cout << "Print Base\n"; }
int data{};
};
struct Child1 : public Base {
Child1(int d, std::string s) : Base(d) { std::cout << "Constructor Child1 " << d << " " << s << "\n"; }
virtual ~Child1() { std::cout << "Destructor Child1\n"; }
virtual void print() { std::cout << "Print Child1: " << data << "\n"; }
};
struct Child2 : public Base {
Child2(int d, char c, long l) : Base(d) { std::cout << "Constructor Child2 " << d << " " << c << " " << l << "\n"; }
virtual ~Child2() { std::cout << "Destructor Child2\n"; }
virtual void print() { std::cout << "Print Child2: " << data << "\n"; }
};
struct Child3 : public Base {
Child3(int d, long l, char c, std::string s) : Base(d) { std::cout << "Constructor Child3 " << d << " " << l << " " << c << " " << s << "\n"; }
virtual ~Child3() { std::cout << "Destructor Child3\n"; }
virtual void print() { std::cout << "Print Child3: " << data << "\n"; }
};
using UPTRB = std::unique_ptr<Base>;
template <class Child, typename ...Args>
UPTRB createClass(Args...args) { return std::make_unique<Child>(args...); }
// The Factory ----------------------------------------------------------------------------------------
template <class Key, class Object>
class Factory
{
std::map<Key, std::any> selector;
public:
Factory() : selector() {}
Factory(std::initializer_list<std::pair<const Key, std::any>> il) : selector(il) {}
template<typename Function>
void add(Key key, Function&& someFunction) { selector[key] = std::any(someFunction); };
template <typename ... Args>
Object create(Key key, Args ... args) {
if (selector.find(key) != selector.end()) {
return std::any_cast<std::add_pointer_t<Object(Args ...)>>(selector[key])(args...);
}
else return nullptr;
}
};
int main()
{
Factory<int, UPTRB> factory{
{1, createClass<Child1, int, std::string>},
{2, createClass<Child2, int, char, long>}
};
factory.add(3, createClass<Child3, int, long, char, std::string>);
// Some test values
std::string s1(" Hello1 "); std::string s3(" Hello3 ");
int i = 1; const int ci = 1; int& ri = i; const int& cri = i; int&& rri = 1;
UPTRB b1 = factory.create(1, 1, s1);
UPTRB b2 = factory.create(2, 2, '2', 2L);
UPTRB b3 = factory.create(3, 3, 3L, '3', s3);
b1->print();
b2->print();
b3->print();
b1 = factory.create(2, 4, '4', 4L);
b1->print();
return 0;
}

Wrapping up factory methods

I have 2 structs whose constructors accept different numbers and types of parameters passed in.
For example,
struct A:Base
{
A(int i, char c){}
};
struct B:Base
{
B(char c){}
};
And I also have a factory method to create these 2 structs's objects,
struct F
{
Base* Do(int i)
{
if (i==0)
{
return new A(i,'c');
}
else
{
return new B('c');
}
}
};
Now that I try to improve my Factory F like this
struct F
{
template<int i, class X>
Base* Do();
template<class X>
Base* Do<0>()
{
return new X(i, 'c');
}
template<class X>
Base* Do<1>()
{
return new X('c');
}
};
The only thing I am not interested in this method is that I have to write a lot of specialized templates in case I have plenty of structs A,B,C,... but I only love templates and I don't like return new X(...).
So my questions are:
How can I minimize the long code but still use templates ?
How can I stop returning a pointer to the base class ? Dynamic allocation sux, I prefer slow and tender classic allocators on the stack for my factory.
I like to use variadic templates for the arguments of my structs' ctors.
std::any and variadic templates will be your friend. Yuu can store anything in std::any. The any_cast will be a bit of a problem.
See the following working code:
#include <iostream>
#include <map>
#include <utility>
#include <any>
// Some demo classes ----------------------------------------------------------------------------------
struct Base {
Base(int d) : data(d) {};
virtual ~Base() { std::cout << "Destructor Base\n"; }
virtual void print() { std::cout << "Print Base\n"; }
int data{};
};
struct Child1 : public Base {
Child1(int d, std::string s) : Base(d) { std::cout << "Constructor Child1 " << d << " " << s << "\n"; }
virtual ~Child1() { std::cout << "Destructor Child1\n"; }
virtual void print() { std::cout << "Print Child1: " << data << "\n"; }
};
struct Child2 : public Base {
Child2(int d, char c, long l) : Base(d) { std::cout << "Constructor Child2 " << d << " " << c << " " << l << "\n"; }
virtual ~Child2() { std::cout << "Destructor Child2\n"; }
virtual void print() { std::cout << "Print Child2: " << data << "\n"; }
};
struct Child3 : public Base {
Child3(int d, long l, char c, std::string s) : Base(d) { std::cout << "Constructor Child3 " << d << " " << l << " " << c << " " << s << "\n"; }
virtual ~Child3() { std::cout << "Destructor Child3\n"; }
virtual void print() { std::cout << "Print Child3: " << data << "\n"; }
};
using UPTRB = std::unique_ptr<Base>;
template <class Child, typename ...Args>
UPTRB createClass(Args...args) { return std::make_unique<Child>(args...); }
// The Factory ----------------------------------------------------------------------------------------
template <class Key, class Object>
class Factory
{
std::map<Key, std::any> selector;
public:
Factory() : selector() {}
Factory(std::initializer_list<std::pair<const Key, std::any>> il) : selector(il) {}
template<typename Function>
void add(Key key, Function&& someFunction) { selector[key] = std::any(someFunction); };
template <typename ... Args>
Object create(Key key, Args ... args) {
if (selector.find(key) != selector.end()) {
return std::any_cast<std::add_pointer_t<Object(Args ...)>>(selector[key])(args...);
}
else return nullptr;
}
};
int main()
{
Factory<int, UPTRB> factory{
{1, createClass<Child1, int, std::string>},
{2, createClass<Child2, int, char, long>}
};
factory.add(3, createClass<Child3, int, long, char, std::string>);
// Some test values
std::string s1(" Hello1 "); std::string s3(" Hello3 ");
int i = 1; const int ci = 1; int& ri = i; const int& cri = i; int&& rri = 1;
UPTRB b1 = factory.create(1, 1, s1);
UPTRB b2 = factory.create(2, 2, '2', 2L);
UPTRB b3 = factory.create(3, 3, 3L, '3', s3);
b1->print();
b2->print();
b3->print();
b1 = factory.create(2, 4, '4', 4L);
b1->print();
return 0;
}

Template specialization behavior example

I am trying to understand template specialization in C++. I have read other forums, but cannot get it working in practice. I am trying to learn with a very simple example which I will explain.
What I would like to accomplish: I want foo to exhibit different behaviors based on the type. The code below does not work, but I have commented the behavior I would like to see. Could someone please fill in the lines that I commented. Please let me know if anything is unclear.
#include <iostream>
#include <string>
template <typename T>
class my_template
{
public:
foo() {return 0} // default behavior if there does not exist foo() function for the specified type
};
template <>
class my_template<int>
{
public:
// implement foo function: should return -1 if the type = int
};
template <>
class my_template<long>
{
public:
// implement foo function: should return 100 if the type = long
};
int main()
{
my_template<int> x;
my_template<long> y;
my_template<double> z;
std::cout << x.foo() << "\n"; // print -1
std::cout << y.foo() << "\n"; // print 100
std::cout << z.foo() << "\n"; // print 0
return 0;
}
Just to show you a few different approaches.
If you use a metafunction approach, then nothing will ever be done at run-time (guaranteed):
template<typename>
struct my_template{
enum { value = 0 };
};
template<>
struct my_template<int>{
enum { value = -1 };
};
template<>
struct my_template<long>{
enum { value = 100 };
};
int main(){
std::cout << "float: " << my_template<float>::value << '\n';
std::cout << "int: " << my_template<int>::value << '\n';
std::cout << "long: " << my_template<long>::value << '\n';
}
Or you could use a template variable ( C++14 ):
template<typename>
constexpr int my_value = 0;
template<>
constexpr int my_value<int> = -1;
template<>
constexpr int my_value<long> = 100;
int main(){
std::cout << "float: " << my_value<float> << '\n';
std::cout << "int: " << my_value<int> << '\n';
std::cout << "long: " << my_value<long> << '\n';
}
Or use a template function:
template<typename T>
int func_impl(T){ return 0; }
int func_impl(int){ return -1; }
int func_impl(long){ return 100; }
template<typename T>
int func(){
return func_impl(T(0));
}
int main(){
std::cout << "float: " << func<float>() << '\n';
std::cout << "int: " << func<int>() << '\n';
std::cout << "long: " << func<long>() << '\n';
}
template <typename T>
class my_template
{
public:
int foo() {return 0;} // default behavior
};
template <>
class my_template<int>
{
public:
int foo() {return -1;}
};
Is that enough?

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)