Header file has this.
std::string m_StrId;
Source file has this.
const std::string& getStringId() const { return m_StrId; }
I am seeing these two lines of code.
What is the purpose of the second const here ?
Related
I’am having trouble with const data.
It should be easy, but…
(working with ESP32 on PlatformIO)
This is OK:
*main.cpp*
const char test[] = { 1,2,3 };
main() {
char buff[10];
strcpy(buff, (char *) test);
}
…but if the const data are on another file, linker returns Undefined Reference to test:
*main.cpp*
extern const char test[];
main() {
char buff[10];
strcpy(buff, (char *) test);
}
--------------------------
*file.cpp*
const char test[] = { 1,2,3 };
Thanks for help!
You must include the file where you define your variables
Here is an example:
main.cpp
#include <pathTo/file.cpp>
main() {
char buff[10];
strcpy(buff, (char *) test);
}
file.cpp
#ifndef file_cpp
#define file_cpp
const char test[] = { 1,2,3 };
#endif
This bugged me also!
It seems that in C++ const variables not always get realized. To force a variable to be realized, add 'extern' also to its definition:
*file.cpp*
extern const char test[] = { 1,2,3 };
Worked for me on platform.io + ESP32
Colleagues programmers would like information, I set up through esp32 a rest application according to the example of Espressif. Everything is working but it has a detail that I couldn't solve about a variable.
this is part of the espressif example
/* Simple handler for getting system handler */
static esp_err_t system_info_get_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "application/json");
cJSON *root = cJSON_CreateObject();
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
cJSON_AddStringToObject(root, "version", IDF_VER);
cJSON_AddNumberToObject(root, "cores", chip_info.cores);
const char *sys_info = cJSON_Print(root);
httpd_resp_sendstr(req, sys_info);
free((void *)sys_info);
cJSON_Delete(root);
return ESP_OK;
}
What I did I replaced
const char * sys_info
for
std :: string sys_info
and removed
free((void *)sys_info);
static esp_err_t system_info_get_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "application/json");
cJSON *root = cJSON_CreateObject();
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
cJSON_AddStringToObject(root, "version", IDF_VER);
cJSON_AddNumberToObject(root, "cores", chip_info.cores);
//const char *sys_info = cJSON_Print(root); (replace)
std::string sys_info = cJSON_Print(root);
httpd_resp_sendstr(req, sys_info);
//free((void *)sys_info); (removed)
cJSON_Delete(root);
return ESP_OK;
}
this is working but the only problem is that whenever I make a request like for example in the postman I keep monitoring the memory and with each request the impression it creates a new variable std :: string sys_info because the available memory drops, work as in the first example with free ((void *) sys_info); the available memory does not change. Can someone give me guidance
cJSON_Print still allocates so you need to free the original.
When you make a std::string from a const char*, it copies to new memory.
If you really want a std::string you should have
const char * const tmp = cJSON_Print(root);
std::string sys_info = tmp;
free((void *)tmp); //needed the pointer after copying into string in order to free
There is no benefit to this however so you should stick with the old version.
I have a structure that should be statically initialized.
struct Option
{ char Option[8];
void (*Handler)(const char* value);
};
void ParseInto(const char* value, const char** target); // string option
void ParseInto(const char* value, int* target, int min, int max); // int option
static int count = 1;
static const char* name;
static const Option OptionMap[] =
{ { "count", [](const char* value) { ParseInto(value, &count, 1, 100); } }
, { "name", [](const char* value) { ParseInto(value, &name); } }
// ...
};
Up to this point it works.
To get rid of repeating the lambda function definition over and over (there are dozens) I want to use a factory like this:
struct Option
{ const char Option[8];
const void (*Handler)(const char* value);
template<typename ...A>
Option(const char (&option)[8], A... args)
: Option(option)
, Handler([args...](const char* value) { ParseInto(value, args...); })
{}
};
static const Option OptionMap[] =
{ { "count", &count, 1, 100 }
, { "name", &name }
};
This does not work for two reasons:
I did not find a type for the first constructor parameter option that perfectly forwards the initialization of the character array. The difficult part is that the length of the assigned array does not match the array length in general.
The even harder part is that the lambda function has a closure and therefore cannot decay to a function pointer. But all parameters are compile time constants. So It should be possible to make the constructor constexpr. However, lambdas seem not to support constexpr at all.
Anyone an idea how to solve this challenge?
The current work around is a variadic macro. Not that pretty, but of course, it works.
Context is C++11. I would not like to upgrade for now, but nevertheless a solution with a newer standard would be appreciated. Problems like this tend to reappear from time to time.
There are some further restrictions by the underlying (old) code. struct Option must be a POD type and the first member must be the character array so a cast from Option* to const char* is valid.
Imagine a typical realization of the PIMPL idiom:
class ObjectImpl;
class Object
{
Object(ObjectImpl* object_impl)
: _impl(object_impl);
private:
ObjectImpl* _impl;
};
What I'm looking for is a way to reuse the same implementation to wrap a type T that's either ObjectImpl or const ObjectImpl but nothing else:
class ObjectImpl;
class Object
{
Object(T* object_impl)
: _impl(object_impl);
private:
// T being either ObjectImpl or const ObjectImpl
T* _impl;
};
What I'm trying to achieve is retaining logical constness through the PIMPL interface so that I'm disallowed by the compiler to call non-const methods on an Object wrapping a const ObjectImpl*.
It's basically just this trick borrowed from one of Scott Meyers Effective C++ books but with an added layer of abstraction:
struct SData
{
const Data* data() const { return _data; }
Data* data() { return _data; }
private:
Data* _data:
};
Of course I could copy the entire class into a class ConstObject and have it wrap a const* Object instead of an Object* but I'm obviously trying to prevent code duplication.
I've also thought about templates but they seem a bit overkill for the task at hand. For one, I want T to only be either ObjectImpl or const ObjectImpl. Secondly, templates seem to work against the idea of PIMPL when exported as a DLL interface. Is there a better solution to go with?
CRTP.
template<class Storage>
struct const_Object_helper {
Storage* self() { return static_cast<D*>(this); }
Storage const* self() const { return static_cast<D*>(this); }
// const access code goes here, get it via `self()->PImpl()`
};
struct const_Object: const_Object_helper<const_Object> {
const_Object( objectImpl const* impl ):pImpl(impl) {}
private:
objectImpl const* pImpl = nullptr;
objectImpl const* PImpl() const { return pImpl; }
template<class Storage>
friend struct const_Object_helper;
};
struct Object: const_Object_helper<Object> {
// put non-const object code here
Object( objectImpl* impl ):pImpl(impl) {}
operator const_Object() const {
return {PImpl()}; // note, a copy/clone/rc increase may be needed here
}
private:
objectImpl* pImpl = nullptr;
objectImpl const* PImpl() const { return pImpl; }
objectImpl* PImpl() { return pImpl; }
template<class Storage>
friend struct const_Object_helper;
};
This is the zero runtime overhead version, but requires the implementation of const_Object_helper and Object_helper to be exposed. As it just involves forwarding stuff to the actual impl, this seems relatively harmless.
You can remove that need by replacing the CRTP part of the helpers with a pure-virtual objectImpl const* get_pimpl() const = 0 and objectImpl* get_pimpl() = 0, then implement them in the derived types.
Another, somewhat crazy, approach would be to use an any augmented with type-erased operations (you also want to teach the type erasure mechanism about const, and that a super_any with fewer interfaces can be implicitly converted over without doing another layer of wrapping).
Here we define certain operations, say print and dance and boogie:
auto const print = make_any_method<void(std::ostream&), true>(
[](auto&&self, std::ostream& s) {
s << decltype(self)(self);
}
);
auto const dance = make_any_method<void()>(
[](auto&&self) {
decltype(self)(self).dance();
}
);
auto const dance = make_any_method<double(), true>(
[](auto&&self) {
return decltype(self)(self).boogie();
}
);
Now we create two types:
using object = super_any< decltype(print), decltype(dance), decltype(boogie) > object;
using const_object = super_any< decltype(print), decltype(boogie) >;
Next, augment the super_any with the ability to assign-from sources with strictly weaker requirements.
Our object o; can (o->*dance)(). Our const_object co; can double d = (co->*boogie)();.
Anything can be stored in an object that supports the operations described by print, boogie and dance, plus the requirements of any (copy, destroy, assign). Anything at all.
Similarly, the const_object supports anything that can be described by print and boogie and copy/destroy/assign.
Derived types from object or const_object can add operator overloading features easily.
This technique is advanced. You can use boost::type_erasure to do it, probably slicker than this sketch.
I would suggest the following general design pattern. It wastes an additional pointer, but will enforce the requirement that the const object will be able to only access const methods of the private object:
class ObjectImpl;
class const_Object {
public:
const_Object(const ObjectImpl* object_impl)
: _impl(object_impl);
// Only const methods
private:
const ObjectImpl* _impl;
};
class Object : public const_Object
{
Object(ObjectImpl* object_impl)
: const_Object(object_impl), _impl(object_impl);
// non-const methods go here.
private:
ObjectImpl* _impl;
};
I'm trying to learn how to use Bonjour using this blog article as a reference:
http://marknelson.us/2011/10/25/dns-service-discovery-on-windows/
I've download sample project linked at the bottom of that page, it works like charm. Now I'm trying to reproduce service discovery from scratch in my console application:
#include <iostream>
#include <assert.h>
#include "dns/dns_sd.h"
class CDnsSd
{
public:
bool discoverAsync ();
private:
static void DNSSD_API onDiscoveryFinished (DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
DNSServiceErrorType errorCode, const char *serviceName, const char *regtype,
const char *replyDomain, void *context);
};
bool CDnsSd::discoverAsync()
{
DNSServiceRef client = NULL;
const DNSServiceErrorType err = DNSServiceBrowse( &client, 0, 0, ""_services._dns-sd._udp"", "", onDiscoveryFinished, this );
return err == kDNSServiceErr_NoError;
}
void DNSSD_API CDnsSd::onDiscoveryFinished( DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context )
{
std::cout << __FUNCTION__;
}
void main ()
{
CDnsSd dnsSd;
const bool ret = dnsSd.discoverAsync();
assert(ret);
Sleep(10000000);
}
DNSServiceBrowse returns kDNSServiceErr_NoError, but the callback is never called. What's wrong?
You need a main loop processing Bonjour events. Look at the link you provided carefully. It's there in the "Driving the Callbacks" section.
I had to call the method named DNSServiceProcessResult to make it work for my part.
I hope it helped