Template equivalent of #var in macro - c++

In C++ macros you can use #var to get the literal string of the argument passed:
#define PRINT_SIZE(type) \
(std::cout << sizeof(type) << " " << #type << std::endl)
Using this macro, I can write a very simple program which will give me the lengths of specific types on my machine:
PRINT_SIZE(bool);
PRINT_SIZE(char);
…
This does work but I would like to use C++ templates instead. Obtaining the size is easy with the following template function:
template <typename T>
void print_size() {
std::cout << sizeof(T) << std::endl;
}
I can call this function with any type and it will output the size:
print_size<bool>();
print_size<char>();
…
Is there any way I could get a literal "bool" from this anywhere such that the output would be as nice as the one with macros?

It can sortof be done using RTTI (runtime type inference) using typeid:
#include <iostream>
#include <typeinfo>
template <typename T>
void print_size() {
T a;
std::cout << typeid(a).name() << ": " << sizeof(T) << std::endl;
}
int main(){
print_size<bool>();
print_size<char>();
print_size<long>();
return 0;
}
This outputs:
b: 1
c: 1
l: 8

You can use typeid() as in:
int i;
cout << typeid(i).name(); // Most likely will print int but g++ prints i
cout << typeid(int).name(); // Also most likely will print int but g++ prints i
Note that the name it returns depends on the compiler and may be some unusual form of the type. More information here.
Edit:
g++ (4.8) prints only the first letter of fundamental types. For user defined classes, it prints the number of characters in the name followed by the name. Ex:
#include <iostream>
#include <typeinfo>
class myclass
{
myclass() {}
};
class my
{
my() {}
};
int main()
{
std::cout << typeid(int).name() << std::endl;
std::cout << typeid(bool).name() << std::endl;
std::cout << typeid(myclass).name() << std::endl;
std::cout << typeid(my).name() << std::endl;
}
Produces the following output:
i
b
7myclass
2my

Related

Simpler logger function using std::stringstream

I'm trying to write a simple logging function which can handle different types in this format:
LOG("This is one type: " << one_type << " and here is a different type: " << diff_type);
I've been looking at the examples here:
How to use my logging class like a std C++ stream?
stringstream with recursive variadic function?
and this is what I came up with:
#include <iostream>
#include <sstream>
void LOG(std::stringstream& ss)
{
std::cout << ss.str() << std::endl;
}
However, even when I just do:
LOG("Some text");
I get the error:
could not convert ‘(const char*)"Some text"’ from ‘const char*’ to ‘std::stringstream’ {aka ‘std::__cxx11::basic_stringstream<char>’}
How can I implement this?
A common way to solve this is to make LOG a macro that just does text substitution instead. You could define a LOG macro like
#define LOG(to_log) \
do \
{ \
std::cout << to_log << std::endl; \
} while (false)
and then
LOG("This is one type: " << one_type << " and here is a different type: " << diff_type);
would get expanded to
do
{
std::cout << "This is one type: " << one_type << " and here is a different type: " << diff_type << std::endl;
} while (false);
template <typename ... T>
void log(T const& ... t)
{
( std::cout << ... << t );
// maybe want to add a newline?
std::cout << std::endl; // note: '\n' just adds it,
// std::endl flushes the stream...
}
would allow to log (to console!) as:
log("this is an int: ", 1210, " and this is a double: ", 10.12);
Note the commas instead of the stream operator (<<)...
If you want to log to arbitrary streams you might need to add it as yet another parameter (/*...*/ void log(std::ostream& s, T const&... t)) or you might (among other solutions) initialise some singleton that you access from within the logging function:
void initialiseLogging(std::ostream& s)
{
Logger::instance().initialize(s);
}
template <typename ... T>
void log(T const& ... t)
{
// assumes returning a reference:
( Logger::instance().stream() << ... << t );
}
Above variant assumes initialisation being required and logging without yielding undefined behaviour (needs to be documented!). If you want to be able to log without you need to change:
{
// now assuming a pointer being returned!
auto s = Logger::instance().stream();
// variant 1: log to nowhere if not initialised:
if(s)
{
( *s << ... << t );
}
// variant 2: default logging to console
s = s ? s : &std::cout;
( *s << ... << t );
}

eigen: create Vector-like Replicate (access with one index, LinearAccessBit)

I want to create an Eigen::Replicate object that can be accessed like a vector, i.e. with a single index. I got that to work with the fixed-size replicate<Index,Index>(), which I can't use in reality, the non-one factor is not a compile-time constant. It also works when manually creating a Replicate object, but I feel like I'm just overlooking the obvious way of using a replicate function to achieve this:
#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
int main(){
Vector3i v (3);
v << 0,1,2;
constexpr int nReplications {2};
auto replDynamic { v.replicate(nReplications, 1) };
/* with a dynamic replication, two indexes are required to access a coeff */
std::cout << "5th entry: " << replDynamic(4,0) << '\n';
auto replFixed { v.replicate<nReplications, 1>() };
/* I want to use only one index, but I require the number of replications
* in one dimension to be dynamic */
std::cout << "5th entry: " << replFixed(4) << '\n';
/* don't know how to access the VectorwiseOp variant */
// auto replVector { v.replicate(nReplications) };
// std::cout << "5th entry: " << replVector(4) << '\n';
/* this function doesn't exist */
// auto replDefined { v.replicate<Dynamic,1>(nReplications, 1) };
// std::cout << "5th entry: " << replDefined(4) << '\n';
/* I'd rather not define it manually (it's not the intended way), but it works */
Replicate<Vector3i,Dynamic,1> replManual { v, nReplications, 1 };
std::cout << "5th entry: " << replManual(4) << '\n';
return 0;
}
The source code shows VectorwiseOp<...>::replicate(Index factor) in line 134, which sounds like what I need, but I don't seem to be able to access it.
And a function such as replicate<Index,Index>(Index,Index) doesn't exist.
Assuming I understand what you are asking, since a Vector3i is a one column Eigen::Matrix, you can get a VectorwiseOp<...> expression template from a Vector3i (say) by using the colwise() function and then call the one argument replicate with that.
That is,
#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
int main() {
Vector3i v(3);
v << 0, 1, 2;
auto foo = v.colwise().replicate(2);
std::cout << "5th entry: " << foo(4) << '\n';
return 0;
}
Note though that using type deduction on a expression template, or "pseudo expression" as they are called in the Eigen documentation, is generally a bad idea i.e. writing Eigen::Matrix<int, 6, 1> foo = v.colwise().replicate(2) is safer; the Eigen documentation mentions the issue here.
By adding a .reshaped() after the replicate(...) call, the ColsAtCompileTime are set to 1, and therefore, the resulting object can be accessed like a vector:
#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
int main(){
Vector3i v (3);
v << 0,1,2;
constexpr int nReplications {2};
auto replReshaped { v.replicate(nReplications, 1).reshaped() };
std::cout << "5th entry: " << replReshaped(4) << '\n';
return 0;
}

C++ scoping? issue when passing an array to a function [duplicate]

This question already has answers here:
Arrays passed to function in C++ giving different lengths
(5 answers)
Closed 5 years ago.
Consider the code below. This generates the following output:
Length: 64
Testfn: 8
Length again: 64
I am having trouble understanding why the output at the test-function is not equal to the output at the main function. Taking into account that the output at the test-function is equal to 8, I assume that this is because sizeof(arg) gets the size of the pointer instead of the array itself.
This would all seem very logical to me, but why doesn't sizeof give that same value in the main function? And how would I fix it? I have tried several things with dereferencing, but this does not seem to give any difference whatsoever.
#include <iostream>
void test(int arg[]) {
std::cout << "Testfn: " << sizeof(arg) << std::endl;
}
int main() {
int int_arr[16];
std::cout << "Length: " << sizeof int_arr << std::endl;
test(int_arr);
std::cout << "Length again: " << sizeof int_arr << std::endl;
}
The function parameter
void test(int arg[]) {
is adjusted to pointer to type int. That is the following function declarations
void test(int arg[16]);
void test(int arg[]);
void test(int *arg);
are equivalent.
So inside the function there is used sizeof( int * ) that depending on the using platform usually equal to either 4 or 8.
You could declare the function in C++ like
void test(int ( &arg )[16]) {
std::cout << "Testfn: " << sizeof(arg) << std::endl;
}
that is to declare the parameter as reference to the array and in this case you will get the expected result.
If you use C++11 or higher, the std::array is what you need:
#include <iostream>
#include <array>
template<size_t N>
void test(const std::array<int, N>& arg) {
std::cout << "Testfn: " << arg.size() << std::endl;
}
int main() {
std::array<int, 16> int_arr;
std::cout << "Length: " << int_arr.size() << std::endl;
test(int_arr);
std::cout << "Length again: " << int_arr.size() << std::endl;
}

Using a boost::fusion::map in boost::spirit::karma

I am using boost spirit to parse some text files into a data structure and now I am beginning to generate text from this data structure (using spirit karma).
One attempt at a data structure is a boost::fusion::map (as suggested in an answer to
this question). But although I can use boost::spirit::qi::parse() and get data in it easily, when I tried to generate text from it using karma, I failed.
Below is my attempt (look especially at the "map_data" type). After some reading and playing around with other fusion types, I found boost::fusion::vector and BOOST_FUSION_DEFINE_ASSOC_STRUCT. I succeeded to generate output with both of them, but they don't seem ideal: in vector you cannot access a member using a name (it is like a tuple) -- and in the other solution, I don't think I need both ways (member name and key type) to access the members.
#include <iostream>
#include <string>
#include <boost/spirit/include/karma.hpp>
#include <boost/fusion/include/map.hpp>
#include <boost/fusion/include/make_map.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/fusion/include/transform.hpp>
struct sb_key;
struct id_key;
using boost::fusion::pair;
typedef boost::fusion::map
< pair<sb_key, int>
, pair<id_key, unsigned long>
> map_data;
typedef boost::fusion::vector < int, unsigned long > vector_data;
#include <boost/fusion/include/define_assoc_struct.hpp>
BOOST_FUSION_DEFINE_ASSOC_STRUCT(
(), assocstruct_data,
(int, a, sb_key)
(unsigned long, b, id_key))
namespace karma = boost::spirit::karma;
template <typename X>
std::string to_string ( const X& data )
{
std::string generated;
std::back_insert_iterator<std::string> sink(generated);
karma::generate_delimited ( sink, karma::int_ << karma::ulong_, karma::space, data );
return generated;
}
int main()
{
map_data d1(boost::fusion::make_map<sb_key, id_key>(234, 35314988526ul));
vector_data d2(boost::fusion::make_vector(234, 35314988526ul));
assocstruct_data d3(234,35314988526ul);
std::cout << "map_data as_vector: " << boost::fusion::as_vector(d1) << std::endl;
//std::cout << "map_data to_string: " << to_string(d1) << std::endl; //*FAIL No 1*
std::cout << "at_key (sb_key): " << boost::fusion::at_key<sb_key>(d1) << boost::fusion::at_c<0>(d1) << std::endl << std::endl;
std::cout << "vector_data: " << d2 << std::endl;
std::cout << "vector_data to_string: " << to_string(d2) << std::endl << std::endl;
std::cout << "assoc_struct as_vector: " << boost::fusion::as_vector(d3) << std::endl;
std::cout << "assoc_struct to_string: " << to_string(d3) << std::endl;
std::cout << "at_key (sb_key): " << boost::fusion::at_key<sb_key>(d3) << d3.a << boost::fusion::at_c<0>(d3) << std::endl;
return 0;
}
Including the commented line gives lots of pages of compilation errors, among which notably something like:
no known conversion for argument 1 from ‘boost::fusion::pair’ to ‘double’
no known conversion for argument 1 from ‘boost::fusion::pair’ to ‘float’
Might it be that to_string needs the values of the map_data, and not the pairs? Though I am not good with templates, I tried to get a vector from a map using transform in the following way
template <typename P>
struct take_second
{
typename P::second_type operator() (P p)
{
return p.second;
}
};
// ... inside main()
pair <char, int> ff(32);
std::cout << "take_second (expect 32): "
<< take_second<pair<char,int>>()(ff) << std::endl;
std::cout << "transform map_data and to_string: "
<< to_string(boost::fusion::transform(d1, take_second<>())); //*FAIL No 2*
But I don't know what types am I supposed to give when instantiating take_second and anyway I think there must be an easier way to get (iterate over) the values of a map (is there?)
If you answer this question, please also give your opinion on whether using an ASSOC_STRUCT or a map is better.
I think I noticed your question on the [spirit-general] list earlier.
It got 14 views there - and I did some fairly deep investigation. Sadly, to the best of my knowledge I don't think Spirit has any support for associate Fusion structures.
In fact, outside MSM and Phoenix, there was no place in boost where I see fusion::map being used.
Is there a chance you could just use std::map/std::pair instead? Here's a tiny proof of concept:
#include <boost/spirit/include/karma.hpp>
#include <boost/fusion/adapted.hpp>
int main()
{
const auto data = std::map<std::string, double> {
{ "pi", 3.1415925 },
{ "e", 2.718281828 },
{ "Answer", 42 } };
namespace karma = boost::spirit::karma;
std::cout << karma::format((karma::string << " = " << karma::double_) % karma::eol, data)
<< std::endl;
}
Output:
Answer = 42.0
e = 2.718
pi = 3.142

Need a macro to create a std::string from a std::ostringstream and a << arg list

I want to write a macro that takes as its only argument a list of std::ostream& operator<< concatenated objects and passes the consolidated string as a single std::string object to a function. The ability to pass the consolidated string to a function is key; in the example below I am aware that the example itself could be rewritten to work simply by defining the macro to ERR_MSG(inputs) std::cout << "ERROR: " << inputs, but sending the output to std::cout is not the goal, it's just the test objective I chose for the example.
I'm using GCC 4.1.2 (Red Hat 4.1.2-52) and upgrading it is not an option. Here's a very boiled-down version of what I've tried:
#include <sstream>
#include <iostream>
#define ERR_MSG(inputs) errMsg(std::ostringstream().str()) // 1
#define ERR_MSG(inputs) errMsg((std::ostringstream()<<inputs).str()) // 2
<aReturnType> errMsg(const std::string& msg) // use with 1 & 2
{
std::cout << "\nERROR: " << msg << "\n\n";
return <someObjectCreatedBasedOnTheInput>;
}
#define ERR_MSG(inputs) errMsg(std::ostringstream()<<inputs) // 3
<aReturnType> errMsg(const std::ostringstream& msg) // use with 3
{
std::cout << "\nERROR: " << msg.str() << "\n\n";
return <someObjectCreatedBasedOnTheInput>;
}
int main()
{
ERR_MSG("A number: " << 24 << ", a char: " << 'c' << ", that's all!");
}
Macro #1 compiles, but of course prints nothing but "" for the message. Neither macros 2 & 3 compile, with the following errors:
#define ERR_MSG(inputs) errMsg((std::ostringstream()<<inputs).str()) // 2
error: ‘struct std::basic_ostream<char, std::char_traits<char> >’ has no member named ‘str’
#define ERR_MSG(inputs) errMsg(std::ostringstream()<<inputs) // 3
no matching function for call to ‘errMsg(std::basic_ostream<char, std::char_traits<char> >&)’
note: candidates are: char* errMsg(const std::string&)
note: char* errMsg(const std::ostringstream&)
I am not interested in how I could rewrite this without macros; I can do that quite easily myself.
=== UPDATE: ===
I forgot to mention that in its real use case, the function called by the macro returns an object that may be used by the caller of the macro. That invalidates any macro implementations that cannot be implemented in a single expression whose result is the returned type of the function called by the macro. The "do nothing" implementation of the macro (for release builds) will simply pass an empty std::string to the function regardless of what the "inputs" are. Sorry for not mentioning that earlier.
Your current problem is that all of the various operator<< functions return an ostream&, not an ostringstream&. You can solve that with a simple cast:
#define ERR_MSG(inputs) errMsg((static_cast<std::ostringstream&>(std::ostringstream().flush() << inputs)).str())
The flush is needed because std::ostringstream() is a temporary. Therefore, you can't call functions on it that take an lvalue reference (ie: std::ostream&). Functions like most operator<< variants. All the flush call does is return the this pointer as an lvalue reference.
If you are willing to use some GCC extension, you could declare an actual ostringstream inside the macro in a block, so that the .str() method can be used without casting:
#define ERR_MSG(inputs) \
do { std::ostringstream _s_; _s_<<inputs;errMsg(_s_.str()); } while(false)
Demo: http://ideone.com/clone/y56lc
Use do { } while (false) idiom to make a few lines macro.
#define ERR_MSG(inputs) \
do { \
std::ostringstream osERR_MSG; \
osERR_MSG << inputs; \
errMsg(osERR_MSG.str()); \
} while (false)
int main() {
if (1) ERR_MSG("A number: " << 24 << ", a char: " << 'c' << ", that's all!");
else return 0;
}
The reason I made such strange name osERR_MSG is to avoid as much as possible cases like this:
int osERR_MSG = 7;
ERR_MSG(osERR_MSG);
#include <sstream>
#include <iostream>
#define ERR_MSG(inputs) errMsg(std::ostringstream().flush()<<inputs)
int errMsg(std::ostream& os)
{
std::ostringstream& oss(static_cast<std::ostringstream&>(os));
const std::string& str(oss.str());
std::cout << "\nERROR: " << str << "\n\n";
return str.length();
}
int main()
{
int i = ERR_MSG("A number: " << 24 << ", a char: " << 'c' << ", that's all!");
std::cout << i << "\n";
}
I'd not create an std::ostringstream but rather have a function called from the destructor of a class derived from std::ostream. Here is an example of this approach:
#include <sstream>
#include <iostream>
void someFunction(std::string const& value)
{
std::cout << "someFunction(" << value << ")\n";
}
void method(std::string const& value)
{
std::cout << "method(" << value << ")\n";
}
class FunctionStream
: private virtual std::stringbuf
, public std::ostream
{
public:
FunctionStream()
: std::ostream(this)
, d_function(&method)
{
}
FunctionStream(void (*function)(std::string const&))
: std::ostream(this)
, d_function(function)
{
}
~FunctionStream()
{
this->d_function(this->str());
}
private:
void (*d_function)(std::string const&);
};
int main(int ac, char* av[])
{
FunctionStream() << "Hello, world: " << ac;
FunctionStream(&someFunction) << "Goodbye, world: " << ac;
}
The example use doesn't use a macro but this can be wrapped easily around the above use of FunctionStream(). Note, that in a macro you probably want to make sure that the type seen by the user of the macro is of type std::ostream& rather than a temporary type so it can be used directly with user defined output operators. To this end you should have an insertion for one of the types directly supported by std::ostream which doesn't have any effect but returns an std::ostream&, for example:
#define SomeMacro(output) FunctionStream(&someFunction) << "" << output
Reinstating Nicol's answer as its the best so far:
Your current problem is that all of the various operator<< functions return an ostream&, not an ostringstream&. You can solve that with a simple cast:
#define ERR_MSG(inputs) errMsg((static_cast<std::ostringstream&>(std::ostringstream().flush() << inputs)).str())
Of course, this still has the problem (like all the answers here) that something like
ERR_MSG(x ? "x is true" : "x is false")
will misbehave in an odd and confusing manner.