int testcases;
cin >> testcases;
Is there a way to shorten the above to one line? Or more generally, can anyone provide me a good resource where I can read about code shortage that doesn't necessarily affect the readability?
There isn't a whole lot to shorten there; however if you were going to be writing many instances of the above, you could write a helper-function like this:
int readInt()
{
int i;
cin >> i;
return i;
}
... then your many instances could be just one line apiece:
int testcases = readInt();
Building on Jeremy's idea, you could make a function template that creates and reads into many variables at once:
#include <iostream>
#include <stdexcept>
#include <string>
#include <tuple>
#include <utility>
template<class... Types, size_t... I>
void readthem(std::istream& is, std::tuple<Types...>& rv, std::index_sequence<I...>) {
// A C++17 fold expression
(is >> ... >> std::get<I>(rv));
}
template<class... Types, class Indices = std::make_index_sequence<sizeof...(Types)>>
auto readvars(std::istream& is) {
std::tuple<Types...> rv; // A tuple consisting of the types you want
readthem(is, rv, Indices{});
if(not is) throw std::runtime_error("Input failed");
return rv;
}
int main() {
// read an int, a double and a std::string
auto[i, d, s] = readvars<int, double, std::string>(std::cin);
std::cout
<< i << '\n'
<< d << '\n'
<< s << '\n';
}
Related
Let ss be a std::stringstream. How to specify a concept for (ss << some_type).str() is a std::string?
Here is the code I have so far:
#include <iostream>
#include <sstream>
namespace detail {
template< class T, class U >
concept SameHelper = std::is_same_v<T, U>;
}
template< class T, class U >
concept same_as = detail::SameHelper<T, U> && detail::SameHelper<U, T>;
template<typename T>
concept ssToStr = requires(T a, std::stringstream ss) {
{ (ss << a).str() } -> same_as<std::string>;
};
void call(ssToStr auto obj)
{
std::stringstream ss;
std::cout << (ss << obj).str() << std::endl;
}
int main()
{
call("Hi");
return 0;
}
You can check online that the code does not compile.
The first part of the error messages reads:
<source>:25:5: error: no matching function for call to 'call'
call("Hi");
^~~~
You're missing #include <sstream>
Fixing that gives the error message that contains:
<source>:14:17: note: because '(ss << a).str()' would be invalid: no member named 'str' in 'std::basic_ostream<char>'
{ (ss << a).str() } -> same_as<std::string>;
Which tells you that (ss << obj) evaluates to a std::ostream, which does not have a .str() member. All you have to check is that ss<<a compiles, and you already know that ss.str() results in a string, so you don't need that in your constraint.
Unfortunately, I don't know enough about constraints to create the working code for you.
Thanks to Mooing Duck I was able to get the code running. The running code reads:
#include <iostream>
#include <sstream>
template<typename T>
concept ssToStr = requires(T a, std::stringstream ss) {
{ ss << a };
};
void call(ssToStr auto obj)
{
std::stringstream ss;
ss << obj;
std::cout << ss.str() << std::endl;
}
int main()
{
call("Hi");
return 0;
}
You can run the code online
Given a struct like this:
struct Foo
{
int x;
int y;
double z;
};
BOOST_FUSION_ADAPT_STRUCT(Foo, x, y, z);
I want to generate a string like this:
"{ int x; int y; double z; }"
I have seen how to print the values of a Fusion adapted struct, but here I need to print the types and names only.
How can I do this mostly simply? I'm not married to Boost.Fusion if there's a better way.
I think you can get something similar to what you want by making some slight modifications on the code in this answer. You can easily get the member name using boost::fusion::extension::struct_member_name but, as far as I know, you can't directly get the member type name. You can get the member type using boost::fusion::result_of::value_at (amongst other options) and I've chosen to use Boost.TypeIndex to get its name (in varying degrees of prettiness, depending on the compiler and the types in question). All of this is assuming that you actually need the Fusion adaptation, if you don't you can probably get a simpler approach that does only what you need.
Full Code
Running on WandBox (gcc)
Running on rextester (vc)
#include <iostream>
#include <string>
#include <boost/mpl/range_c.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/include/zip.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/mpl.hpp>
#include <boost/type_index.hpp>
namespace fusion=boost::fusion;
namespace mpl=boost::mpl;
struct Foo
{
int x;
int y;
double z;
};
BOOST_FUSION_ADAPT_STRUCT(Foo, x, y, z);
struct Bar
{
std::pair<int,int> p;
std::string s;
};
BOOST_FUSION_ADAPT_STRUCT(Bar, p, s);
template <typename Sequence>
struct Struct_member_printer
{
Struct_member_printer(const Sequence& seq):seq_(seq){}
const Sequence& seq_;
template <typename Index>
void operator() (Index) const
{
std::string member_type = boost::typeindex::type_id<typename fusion::result_of::value_at<Sequence,Index>::type >().pretty_name() ;
std::string member_name = fusion::extension::struct_member_name<Sequence,Index::value>::call();
std::cout << member_type << " " << member_name << "; ";
}
};
template<typename Sequence>
void print_struct(Sequence const& v)
{
typedef mpl::range_c<unsigned, 0, fusion::result_of::size<Sequence>::value > Indices;
std::cout << "{ ";
fusion::for_each(Indices(), Struct_member_printer<Sequence>(v));
std::cout << "}\n";
}
int main()
{
Foo foo;
print_struct(foo);
Bar bar;
print_struct(bar);
}
You can use the following solution which is compiler dependent (tested on clang / gcc / MSVC) and only works if you have c++14 (should work with c++11 after slight modifications). It does what you want but there may be simpler solutions...
First part is a bit of compiler dependent code to demangle names return by std::type_info::name:
#include <string>
#if defined __GNUC__
#include <cxxabi.h>
std::string demangle (const char *name) {
int status = 0;
return abi::__cxa_demangle(name, 0, 0, &status);
}
#elif defined _WIN32
#include <Windows.h>
#include <DbgHelp.h>
std::string demangle (const char *name) {
char buffer[1024];
UnDecorateSymbolName(name, buffer, sizeof(buffer)/sizeof(*buffer), 0);
return buffer;
}
#endif
Then the "generic" part is quite short:
#include <array>
#include <tuple>
template <typename Tuple, size_t ...Idx>
std::string to_string (std::string vars, std::index_sequence<Idx...>) {
std::array<const char *, std::tuple_size<Tuple>::value> tnames{
typeid(typename std::tuple_element<Idx, Tuple>::type).name()...};
std::stringstream res;
res << "{ ";
for (auto s: tnames) {
size_t end = vars.find(',');
res << demangle(s) << ' ' << vars.substr(0, end) << "; ";
vars = vars.substr(end + 2);
}
res << '}';
return res.str();
}
#define CREATE(S, ...) struct: S { \
using Tuple = decltype(std::make_tuple(__VA_ARGS__)); \
std::string operator()() { \
return to_string<Tuple>(#__VA_ARGS__, \
std::make_index_sequence<std::tuple_size<Tuple>::value>{}); \
}; \
}
The idea is to create a class L that inherits from the specified class (e.g. Foo) and use the __VA_ARGS__ macro to expands the attribute names into std::make_tuple to obtain their types.
The to_string retrieves the std::type_info::name of each elements from a tuple and combines it with the attribute names (e.g. "x, y, z").
The CREATE macro returns a lambda that you can use as follow:
struct Foo {
int x;
int y;
double z;
};
CREATE(Foo, x, y, z) foo_xyz;
#include <iostream>
int main () {
std::cout << foo_xyz() << std::endl;
}
Output:
{ int x; int y; double z; }
Note: Since demangling is compiler dependent, you may not get exactly the same output with all compilers... For instance if you have a std::array<int, 10>:
gcc: std::array<int, 10ul>
clang: std::__1::array<int, 10ul>
msvc: class std::array<int,10>
Note: The usage is "complicated" to support MSVC: Initially I used a lambda inside CREATE so that you could do CREATE(Foo, x, y, z)() without having to bother creating a variable (I do not know how to generate correct name - see initial version of this answer), but MSVC do not like decltype(std::make_tuple(x, y, z)) inside the lambda... (probably a bug).
I have the following class template which has a member variable whose type is determined by the template argument. I want to initialize the value of this member in the constructor, which only takes a std::string. Thus, my problem is that I need to convert std::string to any of several types (int, double, bool, string). I don't think I can specialize just the constructor, and I would rather not specialize the entire class for each type. The problem with my code below is that stringstream stops streaming out when it hits a space:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
template <typename Ty>
struct Test
{
Ty value;
Test(string str) {
stringstream ss;
ss.str(str);
ss >> value;
}
};
int main()
{
Test<int> t1{"42"};
Test<double> t2{"3.14159"};
Test<string> t3{"Hello world"};
cout << t1.value << endl << t2.value << endl << t3.value << endl;
return 0;
}
The output of the above code is:
42
3.14159
Hello
instead of "Hello world". Is there some way to get stringstream to not stop at whitespace, or some other device that will do arbitrary conversions like I need?
This works for me. Just declare a special implementation before the generalized implementation:
#include <iostream>
#include <string>
#include <sstream>
template<typename T>
struct Test {
T value;
Test(std::string);
};
template<>
inline Test<std::string>::Test(std::string str) {
value = str;
}
template<typename T>
inline Test<T>::Test(std::string str) {
std::stringstream ss;
ss.str(str);
ss >> value;
}
int main() {
Test<int> t1{"42"};
Test<double> t2{"3.14159"};
Test<std::string> t3{"Hello world"};
std::cout
<< t1.value << std::endl
<< t2.value << std::endl
<< t3.value << std::endl;
return 0;
}
Here is an ideone working example.
How can I identify if the number is complex in C++?
Is there any built in function like this?:
isComplex(1)->false
C++ is a strongly typed language, and the literal 1 is always an int.
The determination you ask about might be relevant when converting text... isComplex("1"), for that you can attempt streaming:
std::istringstream iss(some_text);
std::complex<double> my_complex;
char c;
if (iss >> my_complex && // conversion possible...
!(iss >> c)) // no unconverted non-whitespace characters afterwards
...use my_complex...
else
throw std::runtime_error("input was not a valid complex number");
Separately, if you're inside a template and not sure whether a type parameter is std::complex, you can test with e.g. std::is_same<T, std::is_complex<double>>::value, for example:
#include <iostream>
#include <complex>
#include <type_traits>
using namespace std;
double get_real(double n) { return n; }
double get_real(const std::complex<double>& n) { return n.real(); }
template <typename T>
std::complex<double> f(T n)
{
if (std::is_same<T, std::complex<double>>::value)
return n * std::complex<double>{1, -1} + get_real(n);
else
return -n;
}
int main()
{
std::cout << f(std::complex<double>{10, 10}) << '\n';
std::cout << f(10.0) << '\n';
}
Output:
(30,0)
(-10,0)
See the code here.
For more complicated functions, you may want to create separate overloads for e.g. double and std::complex<double>, and/or float and std::complex<float>, long double etc..
I wrote my bind function which returns a nullary functor because I don't have boost. Though this code compiles fine, it does not behave as I expected. When I input 2 as the number of numbers and try to enter them, the program terminates the first time I hit return. And, when I debug, it segfaults inside mem_fun_t::operator(). What am I doing wrong here? And how to rectify it?
#include <iostream>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <iterator>
#include <functional>
using namespace std;
namespace MT
{
template<class Operation>
struct binder
{
protected:
Operation _op;
typename Operation::argument_type _arg;
public:
binder(Operation& fn, typename Operation::argument_type arg)
:_op(fn), _arg(arg)
{
}
typename Operation::result_type operator()()
{
return _op(_arg);
}
};
template<class Operation, class Arg>
binder<Operation> bind(Operation op, Arg arg)
{
return binder<Operation>(op, arg);
}
};
int main()
{
vector<int> vNumbers;
vector<char> vOperators;
int iNumCount = 0;
int iNumOperators = 0;
cout << "Enter number of number(s) :) :\n";
cin >> iNumCount;
int iNumber;
cout << "Enter the " << iNumCount << " number(s):\n";
generate_n(back_inserter(vNumbers), iNumCount, MT::bind(mem_fun(&istream::get), &cin));
system("clear");
copy(vNumbers.begin(), vNumbers.end(), ostream_iterator<int>(cout, " "));
cout << endl;
}
istream::get is not the right method to use, as it reads characters, not ints. You'd need to use operator>> (and selecting the right overload is very verbose), or just write a different functor:
template<class T>
struct Extract {
istream &stream;
Extract(istream &stream) : stream (stream) {}
T operator()() {
T x;
if (!(stream >> x)) {
// handle failure as required, possibly throw an exception
}
return x;
}
};
// ...
generate_n(back_inserter(vNumbers), iNumCount, Extract<int>(cin));