error: no match for ‘operator<<’ in C++ code - c++

Good morning,
I'm implementing this class in C++ but it gives some problem with OCTET_STRING type. In fact, removing those variables it works but obviously I need them too.
class MIXIM_API BSMblob : public cObject
{
public:
long MsgCount;
OCTET_STRING TemporaryID;
long DSecond;
long Latitude;
long Longitude;
OCTET_STRING Elevation;
OCTET_STRING PositionalAccuracy;
OCTET_STRING TransmissionAndSpeed;
long Heading;
OCTET_STRING SteeringWheelAngle;
OCTET_STRING AccelerationSet4Way;
OCTET_STRING BrakeSystemStatus;
/*other line of codes */
/** #brief Returns a string with the value of the BSMblobinate. */
std::string info() const;
};
inline std::ostream& operator<<(std::ostream& os, const BSMblob& BSMblob)
{
return os << "(" << BSMblob.MsgCount << "," << BSMblob.TemporaryID
<< "," << BSMblob.DSecond << "," << BSMblob.Latitude
<< "," << BSMblob.Longitude << "," << BSMblob.Elevation
<< "," << BSMblob.PositionalAccuracy << "," << BSMblob.TransmissionAndSpeed
<< "," << BSMblob.Heading << "," << BSMblob.SteeringWheelAngle
<< "," << BSMblob.AccelerationSet4Way << "," << BSMblob.BrakeSystemStatus
<< ")";
}
The error is => error: no match for ‘operator<<’ (operand types are ‘std::basic_ostream’ and ‘const OCTET_STRING’)
P.S. I was also wondering if it is possible to cast a double variable to a OCTET_STRING.
Thank you everybody
Here the OCTET_STRING.h :
#ifndef _OCTET_STRING_H_
#define _OCTET_STRING_H_
#include <asn_application.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct OCTET_STRING {
uint8_t *buf; /* Buffer with consecutive OCTET_STRING bits */
int size; /* Size of the buffer */
asn_struct_ctx_t _asn_ctx; /* Parsing across buffer boundaries */
} OCTET_STRING_t;
extern asn_TYPE_descriptor_t asn_DEF_OCTET_STRING;
asn_struct_free_f OCTET_STRING_free;
asn_struct_print_f OCTET_STRING_print;
asn_struct_print_f OCTET_STRING_print_utf8;
ber_type_decoder_f OCTET_STRING_decode_ber;
der_type_encoder_f OCTET_STRING_encode_der;
xer_type_decoder_f OCTET_STRING_decode_xer_hex; /* Hexadecimal */
xer_type_decoder_f OCTET_STRING_decode_xer_binary; /* 01010111010 */
xer_type_decoder_f OCTET_STRING_decode_xer_utf8; /* ASCII/UTF-8 */
xer_type_encoder_f OCTET_STRING_encode_xer;
xer_type_encoder_f OCTET_STRING_encode_xer_utf8;
per_type_decoder_f OCTET_STRING_decode_uper;
per_type_encoder_f OCTET_STRING_encode_uper;
/******************************
* Handy conversion routines. *
******************************/
/*
* This function clears the previous value of the OCTET STRING (if any)
* and then allocates a new memory with the specified content (str/size).
* If size = -1, the size of the original string will be determined
* using strlen(str).
* If str equals to NULL, the function will silently clear the
* current contents of the OCTET STRING.
* Returns 0 if it was possible to perform operation, -1 otherwise.
*/
int OCTET_STRING_fromBuf(OCTET_STRING_t *s, const char *str, int size);
/* Handy conversion from the C string into the OCTET STRING. */
#define OCTET_STRING_fromString(s, str) OCTET_STRING_fromBuf(s, str, -1)
/*
* Allocate and fill the new OCTET STRING and return a pointer to the newly
* allocated object. NULL is permitted in str: the function will just allocate
* empty OCTET STRING.
*/
OCTET_STRING_t *OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td,
const char *str, int size);
/****************************
* Internally useful stuff. *
****************************/
typedef struct asn_OCTET_STRING_specifics_s {
/*
* Target structure description.
*/
int struct_size; /* Size of the structure */
int ctx_offset; /* Offset of the asn_struct_ctx_t member */
enum asn_OS_Subvariant {
ASN_OSUBV_ANY, /* The open type (ANY) */
ASN_OSUBV_BIT, /* BIT STRING */
ASN_OSUBV_STR, /* String types, not {BMP,Universal}String */
ASN_OSUBV_U16, /* 16-bit character (BMPString) */
ASN_OSUBV_U32 /* 32-bit character (UniversalString) */
} subvariant;
} asn_OCTET_STRING_specifics_t;
#ifdef __cplusplus
}
#endif
#endif /* _OCTET_STRING_H_ */

The error message from the compiler is quite clear and unambiguous: there is no
std::ostream& operator<<(std::ostream&, OCTET_STRING const&);
that it can use. If OCTET_STRING was a sensibly defined C++ type, then said operator would have been implemented. The fact that it's missing either means that OCTET_STRINGs should never be used in I/O, that the class has been provided by somebody not very much versed in the art of programming, or that it's a piece of C code that you're abusing.
To remedy, either abandon the use of OCTET_STRING (best) or provide a definition for said operator (ideally inline) yourself.
Note that OCTET_STRING is not a standard C++ type. It appears to be some C struct and a Windows thing. Using it obviously causes problems, but also will render your code non-portable. I can only highly recommend to avoid using OCTET_STRING. W/o much knowledge of what a OCTET_STRING does, I cannot say what to replace it with, but perhaps you know what you're using it for? I.e. what is the real type of Elevation in your code? It seems that double does the job for most if not all of them.

Just write one:
std::ostream& operator<<(std::ostream& os, const OCTET_STRING& whatever)
{
// print to os
return os;
}

Related

How do I use char* and std::string, interchangeably as well as in combination?

I know a technical definition (char* is a pointer to a char, which behaves similarly to an array, and a string (literal) is an array of char as it is), but how do they actually work? I read through the section on it (most of the tutorial really) on cplusplus.com (but I clearly have to re-read some sections). Still, I tried some practical examples and encountered some frustrating situations.
I created a simple function, void Log(std::string message) {std::cout << message << std::endl;}, and that works great until I try to use it with char* in combination with string. For example, if I have std::string a and char* b, I cannot do Log(a + b), but I can do std::string print = “”; print += a; print += b; Log(print); Why? How should I define my Log(.) function so that I can use it similarly to Log(a+b) regardless of what types they are (at least std::string and char*, but preferably also int and other types)? If that’s possible, at least.
When I do char * a = “some text”;, I get the warning conversion from string literal to ‘char *’ is deprecated. Obviously, this is not good, so why is this happening and how should I avoid this?
Under which circumstances should I prefer one over the other (apart from the obvious that I sometimes am forced because of some API’s, etc)? Is it a good practice, for example, to convert all my char * to string or vice-versa?
In general, my knowledge of char * and strings (and C++ in general) has… room for improvement, so feel free to give some sources for how to get more familiar and comfortable with char *, strings, and any other related types (arrays, etc?). Although, I would very much appreciate it if someone would explain to me the two particular points above, as well.
For example, if I have std::string a and char* b, I cannot do Log(a +
b)
No you can. Here is a demonstrative program
#include <iostream>
#include <string>
void Log(std::string message) {std::cout << message << std::endl;}
int main()
{
std::string a( "Hello " );
const char *b = "GreatName";
Log( a + b );
return 0;
}
Though it is better to declare the function like
void Log( const std::string &message );
For integral types you should use the family of the functions std::to_string.
#include <iostream>
#include <string>
void Log( const std::string &message ) { std::cout << message << std::endl; }
int main()
{
std::string a( "Hello " );
int b = 10;
Log( a + std::to_string( b ) );
return 0;
}
When I do char * a = “some text”;, I get the warning conversion from
string literal to ‘char *’ is deprecated.
String literals in C++ have types of constant character arrays. So you have to write
const char * a = “some text”;
Under which circumstances should I prefer one over the other
In general especially when an argument is build from several objects you should always prefer to declare the corresponding parameter as having the type std::string.

Writing std::string with non-ascii data to file

Below is a simplified example of my problem. I have some external byte data which appears to be a string with cp1252 encoded degree symbol 0xb0. When it is stored in my program as an std::string it is correctly represented as 0xffffffb0. However, when that string is then written to a file, the resulting file is only one byte long with just 0xb0. How do I write the string to the file? How does the concept of UTF-8 come into this?
#include <iostream>
#include <fstream>
typedef struct
{
char n[40];
} mystruct;
static void dump(const std::string& name)
{
std::cout << "It is '" << name << "'" << std::endl;
const char *p = name.data();
for (size_t i=0; i<name.size(); i++)
{
printf("0x%02x ", p[i]);
}
std::cout << std::endl;
}
int main()
{
const unsigned char raw_bytes[] = { 0xb0, 0x00};
mystruct foo;
foo = *(mystruct *)raw_bytes;
std::string name = std::string(foo.n);
dump(name);
std::ofstream my_out("/tmp/out.bin", std::ios::out | std::ios::binary);
my_out << name;
my_out.close();
return 0;
}
Running the above program produces the following on STDOUT
It is '�'
0xffffffb0
First of all, this is a must read:
The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
Now, when you done with that, you have to understand what type represents p[i].
It is char, which in C is a small size integer value with a sign! char can be negative!
Now, since you have cp1252 characters, they are outside the scope of ASCII. This means these characters are seen as negative values!
Now, when they are converted to int, the sign bit is replicated, and when you are trying to print it, you will see 0xffffff<actual byte value>.
To handle that in C, first you should cast to unsigned char:
printf("0x%02x ", (unsigned char)p[i]);
then the default conversion will fill in the missing bits with zeros and printf() will give you a proper value.
Now, in C++ this is a bit more nasty, since char and unsigned char are treated by stream operators as a character representation. So to print them in hex manner, it should be like this:
int charToInt(char ch)
{
return static_cast<int>(static_cast<unsigned char>(ch));
}
std::cout << std::hex << charToInt(s[i]);
Now, direct conversion from char to unsigned int will not fix the problem since silently the compiler will perform a conversation to int first.
See here: https://wandbox.org/permlink/sRmh8hZd78Oar7nF
UTF-8 has nothing to this issue.
Off-topic: please, when you write pure C++ code, do not use C. It is pointless and makes code harder to maintain, and it is not faster. So:
do not use char* or char[] to store strings. Just use std::string.
do not use printf(), use std::cout (or the fmt library, if you like format strings - it will became a future C++ standard).
do not use alloc(), malloc(), free() - in modern C++, use std::make_unique() and std::make_shared().

Convert built-in data type to std::string: memcpy vs snprintf

I have referred to the relevant question and other posts before this. I am also aware that std::to_string() is the best way (but it's not available in few platforms).
While experimenting, I came across a weird issue with memcpy(). For the example sake, assume that we always pass built-in data types (int, char, long) to below function:
template<typename T>
std::string to_string (const T& value)
{
std::string s(16, 0); // Max size captured
::memcpy(&s[0], &value, sizeof(value));
return s;
}
Running this function individually in a sample program works fine. But while plugging into a bigger code base, somehow it gives weird results! i.e. it gives spurious values. (Ubuntu 14.10, g++4.9 -std=c++11)
However, if I convert the above program using sprintf(), it works fine.
template<typename T>
std::string to_string (const T& value)
{
std::string s(16, 0); // Max size captured
s[::snprintf(&s[0], "%d", value)] = 0;
return s;
}
Question:
Am I touching undefined behavior with memcpy() (or even
sprintf())?
Would byte ordering influence this code?
To recap, yes, you do not want to use memcpy(). Using snprintf() you avoid having to convert the number to ASCII yourself. Something like this would probably be preferable though:
template<typename T>
std::string to_string (const T& value)
{
char buf[16];
::snprintf(buf, sizeof(buf), "%d", value);
// ^-- size was missing in your example
return buf;
}
However, you have a big flow in this function because you cannot know what T is going to be. It could be a double and "%d" won't work as expected. Similarly, it could be a string (char const *).
If you want to manually convert a number to ASCII you can use a loop, something like this:
template<typename T>
std::string to_string (T value)
{
char buf[16]; // any int number is less than 16 characters
char *s = buf + sizeof(buf);
*--s = '\0';
do
{
*--s = value % 10 + '0'; // conversion to ASCII, 1 digit at a time
value /= 10;
}
while(value > 0);
return s;
}
WARNING: that function does not properly handle negative numbers. I'll let that one as an exercise for you to handle as required.
Now, if you want to use a C++ way that should work on all systems you mentioned, without boost or C++11.
template<typename T>
std::string to_string (T const& value)
{
std::stringstream ss;
ss << value;
return ss.str();
}
In this case the stringstream knows how to handle T whatever T is, numbers, objects, etc. as long as those things understand the << as in std::cout << "Hello!" << std::endl;.
If you check out one of my project, named as2js, you'd see a file named include/as2js/node.h which declare something like this:
std::ostream& operator << (std::ostream& out, Node const& node);
That means you can later create a node and print it like this:
Node n;
std::out << n << std::endl;
This means your to_string() function would work with my Node objects.
You can find the implementation of all of that under lib/node_display.cpp

How can I overload bitwise AND (&) in c++ that concatenates the left operand (const char []) with the right operand string object) (Homework)

EDIT: The code that immediately follows, is the working version, located within the header
inline char * operator & (const char String1 [], const MyStringClass & String2)
{
int length = strlen (String1) + String2.Length();
char * pTemp = new char [length + 1];
strcpy (pTemp, String1);
strcat (pTemp, String2.GetStr());
return pTemp;
}
This is the first time I've felt the need to ask a question, since I've been unable to find helpful information on my own (via search, Google, book, etc). My course book is C++ Primer 5th Edition and I've read Ch. 14 which covers operator overloading. I'm not necessarily looking for an "answer" but rather a nudge in the right direction (because I do want to learn this stuff).
The assignment has us creating our own string class and overloading a bunch of operators that will take a class object on either side - with exception to the assignment operator which may only take a class object on the left side. I've played around with all sorts of return types (this cannot be a member function; efforts to make this a friend function failed).
/*
Note: return by value, otherwise I get a warning of returning the address
of a local variable, temporary. But no matter the return type or what I'm
returning, I always get the error: C2677: binary '&' : no global operator
found which takes type 'MyStringClass' (or there is no acceptable
conversion)
*/
MyStringClass operator & (const char String1 [], const MyStringClass & String2)
{
/*
The only requirement is that the left side has const char [] so that
(const char []) & (MyStringClass &) will concatenate. There is no return
type requirement; so, I could either try and return a string object or
an anonymous C-type string.
cout << StringOject1 << endl; // this works
cout << (StringObject1 & "bacon") << endl; // so does this;
// another function overloads & such that: obj & const char [] works
cout << ("bacon" & StringObject1) << endl; // but not this
*/
MyStringClass S (String1); // initialize a new object with String1
S.Concat (String2); // public member function Concat() concatenates String2
// onto String1 in S
return S; // this does not work
/* a different way of trying this... */
int Characters = strlen (String1) + String2.Length();
int Slots = Characters;
char * pTemp = new char [Slots + 1];
strcpy (pTemp, String1);
strcat (pTemp, String2.pString); // this won't work; pString is a private
// member holding char * and inaccessible
// making it pointless to try and initialize and return an object with pTemp
}
Have looked at your code and from what I can understand, you're probably looking for something like this:
class MyStringClass
{
public:
const char* data() const;
private:
const char* charptr;
};
const char* MyStringClass::data() const
{
return charptr;
}
MyStringClass operator & (const char String1 [], const MyStringClass & String2)
{
/* a different way of trying this... */
int len = strlen(String1) + String2.Length();
char * pTemp = new char [len + 1]; //total length of both strings
strcpy (pTemp, String1);
strcat (pTemp, String2.data()); // you need to have a public member function that returns the string as const char*
MyStringClass str(pTemp); //requires MyStringClass to have constructor that takes char*
return str; //return the string
}

How to output unsigned/signed char or <cstdint> types as integers with << in C++

Background:
I have template stream operators (e.g. operator << (ostream &, std::vector <T>)) (that output container elements that may possibly be of some 8-bit integer type, (e.g. unsigned char, int_least8_t, et cetera).
Problem:
Default is that these types are output as char (ASCII).
I only used char (or wchar_t or whatever) for ASCII variables, never unsigned/signed types.
How do I get these other 8-bit types to always be output as signed int / unsigned int (numbers) instead, even when the caller doesn't know the type?
First tries:
I have tried (with GCC) for example defining operator << (ostream &, unsigned char) with a cast in it (i.e. stream << static_cast <int> (value). That works for unsigned char values, but then uint8_t still gets output as a char.
The same underlying type (i.e. unsigned/signed char can not be used in overloads, so I can't define an overload of for example operator << (ostream &, int_fast8_t).
You're confusing the actual data held in a variable, with whatever representation you choose for printing it.
Think of it this way: chars, ints, doubles, longs, whatevers, they're all just chunks of memory for you to store numbers in. A char is a number between 0 and 255 (or -128 and 127) -- you can choose to represent it as an ASCII character, or as a number, or as stars in the sky with the aid of OpenGL.
If you want to see the number behind the character 'a', just instruct your program to treat that chunk of memory (that for you contains an 'a') as a number. Use casts. Here:
http://www.cplusplus.com/doc/tutorial/typecasting/
See if that helps!
One way that comes to mind is using type traits to define the output type for each type. You would have to declare that for every type by hand. The traits could be defined as a template struct that is specialized for every data-type that has a different output-type than the data-type itself:
template< T >
struct output_trait {
typedef const T & output_type;
}
In your operator you write:
std::cout << static_cast< output_trait< T >::output_type >( variable ) << std::endl;
This will do no cast by default, but for types for which output_trait is specialized it will do a cast:
template<>
struct output_trait< unsigned char > {
typedef unsigned int output_type;
}
You can simply cast it:
#include<iostream>
int main()
{
uint8_t blah = 65;
std::cout << static_cast<int>(blah) << "\n";
return 0;
}
65
If I have understood you right.. output it like this:
std::cout << ( unsigned int )char << '\n';
Or more c++ style - use static_cast, for example:
int main()
{
char a = 'a';
char b = 97;
std::cout << static_cast< unsigned int >( a ) << '\n';
std::cout << static_cast< unsigned int >( b ) << '\n';
return 0;
}
both std::cout will print the same: the first one - the ASCII code of 'a': 97, the second one - just the value 97, stored in b. Both, a and b, are absolutely the same.
You can cast them before you output them:
std::cout << (unsigned int) container[index];