Suppose there is a class with a few data members, such as this:
struct s {
char c;
int i;
};
If I need a const-pointer to a member, it's simple enough:
auto s::* const ptr = &s::c;
If I try to create a static member of the same type, some weird things start happening...
For instance, this segfaulted the compiler (gcc 4.9.3):
struct s {
char c;
int i;
static auto s::* const static_ptr = &s::c;
};
// internal compiler error: Segmentation fault
// static auto s::* const static_ptr = &s::c;
// ^
Using it as a static member of a different class at least finishes compiling:
struct t {
static auto s::* const static_ptr = &s::c;
};
// error: 'constexpr' needed for in-class initialization of static data member 'char s::* const t::static_ptr' of non-integral type [-fpermissive]
// static auto s::* const static_ptr = &s::c;
// ^
That last error I don't understand, isn't &s::c a constexpr?
I do have a way to make it work, eg:
// also works with `struct s` this way, `struct t` is not needed for this
struct t {
static char s::* const static_ptr;
};
char s::* const t::static_ptr = &s::c;
But for several reasons this is undesirable:
auto cannot be used except in the definition, if it is initialized outside the class then the type must be declared.
Declaring the type explicitly means either repeating the type or repeating the member name (as decltype(s::c)) - more places to maintain the same name = more mistakes possible.
The above is even more of a nuisance with specialized class templates, where for each specialization this would need to be done inside and outside the class.
From this I have a two part question.
1. Why isn't &s::c a constexpr? Is there a way to make it one?
2. Is there a way to specify a static member that is a fixed pointer to a member of another class, with the type automatically determined, without resorting to decltype?
I have tried this as a member of struct s and get the same error (constexpr needed):
static constexpr auto s::* const member_c () {
return &s::c;
}
So I'm at a loss as to what the compiler's issue is with this sort of syntax, it just doesn't make sense to me why a reference to a data member (not an instance member reference) is not a constant at compile time.
Related
I have a class:
class A
{
public:
A (A& in) {} // How to write a constructor from void* ?
int a;
int b;
const void* data() const { return static_cast<const void *>(this); }
};
I need to pass the class data thru a connection, which takes a void* buffer and "returns" also void*. An instance and some function:
A a;
void send(void* x);
void receive(void* x);
How can I type cast the a to send it as a parameter to foo()? The following code is not valid:
foo(static_cast<A&>(a));
How can I then, create a new object from a void* x pointer? What constructor and type cast to implement?
void* pA;
pA = ...
A a_copy {pA};
What would be the difference, if I have a struct not a class? I assume POD class here.
I would like not to use c-style casts, but rather C++ constructs.
How can I type cast the a to send it as a parameter to foo()? The following code is not valid:
foo(static_cast<A&>(a));
I assume you mean send() instead of foo()? If so, your code is not valid because you are casting it to a reference to A, when send() expects a pointer to void. So:
send(static_cast<void *>(&a));
Or, since you already have a member function that does the casting for you:
send(a.data());
How can I then, create a new object from a void* x pointer? What constructor and type cast to implement?
If you really want to do that, then again your constructor should take a pointer to void as argument, not a reference to another A:
class A
{
public:
A(void* in) {...}
...
};
You could then use std::memcpy() to copy all data into the class
A(void *in) {
std::memcpy(this, in, sizeof *this);
};
Of course, this should only be done if A is a POD type.
What would be the difference, if I have a struct not a class? I assume POD class here.
Nothing. A struct and a class are the same, the exception is just that struct defaults to making members public, and a class defaults to private.
I want to write a class that makes use of numerical quadrature. The quadrature order defines the size of some containers that I will use. I would like to make a type alias for such containers and it has to depend on the quadrature order.
The following code shows my trials. It feels suboptimal in the sense that I have to repeat the order in the type alias definition:
#include <array>
class Quadrature
{
public:
static constexpr unsigned int getOrder()
{
return 3;
}
// This line doesn't compile!
//
// using WeightsContainer = std::array<double, getOrder()>;
//
// g++ says "error: 'static constexpr unsigned int Quadrature::getOrder()'
// called in a constant expression before its definition is complete"
// This line compiles, but repeats the order. :-(
using WeightsContainer = std::array<double, 3>;
private:
WeightsContainer container;
};
One solution that I have found is introducing a template parameter Order. But actually I wanted to determine the quadrature order and introducing the template parameter would make it variable.
Is there a possibility to make the order a compile-time constant and use it within my type alias definition?
Edit:
For completeness, I could of course use a preprocessor define. But that feels old-fashioned. :-)
Edit 2:
Okay, I have found another possibility. I could add a function outside the class scope like this:
constexpr unsigned int order()
{
return 3;
}
But that feels wrong, because this is a property of the class and therefore should be within class scope!
One thing you can do is to move the value into a member variable:
class Quadrature
{
private:
static constexpr unsigned int _order = 3;
public:
static constexpr unsigned int getOrder()
{
return _order;
}
using WeightsContainer = std::array<double, _order>;
// ...
};
If you need more complicated computations instead of just return 3, under C++17 you can use a lambda as #Quentin mentioned:
class Quadrature
{
public:
static constexpr auto getOrder = []()
{
return ...;
};
using WeightsContainer = std::array<double, getOrder()>;
// ...
};
Otherwise, you will need to pull the function outside of class scope for reasons mentioned here.
dlopen() is a C function used for dynamically loading shared libraries at runtime. The pattern, in case you're not familiar, is thus:
Call dlopen("libpath", flag) to get a void *handle to the library
Call dlsym(handle, "object_name") to get a void *object to the thing you want from the library
Do what you want with object
Call dlclose (handle) to unload the library.
This is, in C++, a perfect use-case for the so-called aliasing constructor of std::shared_ptr. The pattern becomes:
Construct a std::shared_ptr<void> handle from dlopen("libpath", flag) that will call dlclose() when its destructor is called
Construct a std::shared_ptr<void> object from handle and dlsym(handle, "object_name")
Now we can pass object wherever we want, and completely forget about handle; when object's destructor is called, whenever that happens to be, dlclose() will be called automagically
Brilliant pattern, and it works beautifully. One small problem, though. The pattern above requires a cast from void* to whatever_type_object_is*. If "object_name" refers to a function (which most of the time it does, considering the use-case), this is undefined behavior.
In C, there is a hack to get around this. From the dlopen man page:
// ...
void *handle;
double (*cosine)(double);
// ...
handle = dlopen("libm.so", RTLD_LAZY);
// ...
/* Writing: cosine = double (*)(double)) dlsym(handle, "cos");
would seem more natural, but the C99 standard leaves
casting from "void *" to a function pointer undefined.
The assignment used below is the POSIX.1-2003 (Technical
Corrigendum 1) workaround; see the Rationale for the
POSIX specification of dlsym(). */
*(void **) (&cosine) = dlsym(handle, "cos");
// ...
which obviously works just fine, in C. But is there an easy way to do this with std::shared_ptr?
The pattern above requires a cast from void* to whatever_type_object_is*. If "object_name" refers to a function (which most of the time it does, considering the use-case), this is undefined behavior.
Well this is not entirely true, at least in C++ it is just conditionally-supported.
5.2.10.8 says:
Converting a function pointer to an object pointer type or vice versa is conditionally-supported. The meaning
of such a conversion is implementation-defined, except that if an implementation supports conversions in
both directions, converting a prvalue of one type to the other type and back, possibly with different cvqualification,
shall yield the original pointer value.
So assuming that what dlsym does internally is casting a function pointer to a void*, I believe that you are ok if you just cast it back to a function pointer.
Something like this?
struct dlib
{
public:
template<class T>
std::shared_ptr<T> sym(const char* name) const {
if (!handle) return {};
void* sym = dlsym(handle->get(), name);
if (!sym) return {};
return {reinterpret_cast<T*>(sym), handle};
}
// returns a smart pointer pointing at a function for name:
template<class Sig>
std::shared_ptr<Sig*> pfunc(const char* name) const {
if (!handle) return {};
void* sym = dlsym(handle->get(), name);
if (!sym) return {};
Sig* ret = 0;
// apparently approved hack to convert void* to function pointer
// in some silly compilers:
*reinterpret_cast<void**>(&ret) = sym;
return {ret, handle};
}
// returns a std::function<Sig> for a name:
template<class Sig>
std::function<Sig> function(const char* name) const {
// shared pointer to a function pointer:
auto pf = pfunc(name);
if (!pf) return {};
return [pf=std::move(pf)](auto&&...args)->decltype(auto){
return (*pf)(decltype(args)(args)...);
};
}
dlib() = default;
dlib(dlib const&)=default;
dlib(dlib &&)=default;
dlib& operator=(dlib const&)=default;
dlib& operator=(dlib &&)=default;
dlib(const char* name, int flag) {
void* h = dlopen(name, flag);
if (h)
{
// set handle to cleanup the dlopen:
handle=std::shared_ptr<void>(
h,
[](void* handle){
int r = dlclose(handle);
ASSERT(r==0);
}
);
}
}
explicit operator bool() const { return (bool)handle; }
private:
std::shared_ptr<void> handle;
};
I doubt that hack is needed. As #sbabbi noted, the round-trip to void* is conditionally supported. On a system using dlsym to return function pointers, it better be supported.
You can make a struct to have your pointer to function and handle to library:
template<typename T>
struct dlsymbol {
dlsymbol( const std::string &name, std::shared_ptr<void> handle ) :
m_handle( std::move( handle ) )
{
*(void **)(&m_func) = dlsym( handle.get(), name.c_str );
}
std::shared_ptr<void> m_handle;
T *m_func;
};
auto cosine = std::make_shared<dlsymbol<double(double)>>( "cos", handle );
auto d = cosine->m_func( 1.0 );
I did not compile it, but I think it is sufficient to show the idea.
Say I have a struct (in real life, that's an automaton):
struct automaton
{
bool get_final() const { return final; }
void set_final() { final = true; }
bool final = false;
};
for which I want to provide a view that sees it transposed (iow, reversed, or mirrored). Because I have more than just a single automaton class, I have a class template that wraps my automaton (I really want composition, not inheritance), and bounces all the function calls to the wrapped automaton, reversing what needs to be. For sake of simplicity, here, it just forwards the calls.
By hand, I'd get
template <typename Aut>
struct transposed_by_hand
{
Aut& aut;
auto get_final() const -> bool
{
return aut.get_final();
}
auto set_final() -> void
{
aut.set_final();
}
};
But there are many functions, and I don't want to hard-code so much information (the function signature) in the wrapper. Thanks to variadic templates and perfect forwarding for the incoming arguments, and decltype for the result, it's quite easy to have one macro to factor the definition of all the const member-functions, and another macro for non-const member functions (the difference being precisely the const). Basically, in this case it boils down to this:
template <typename Aut>
struct transposed_with_decltype
{
Aut& aut;
auto get_final() const -> decltype(aut.get_final())
{
return aut.get_final();
}
auto set_final() -> decltype(aut.set_final())
{
aut.set_final();
}
};
This works well for non-const automata, but breaks if I wrap a const automaton:
int main()
{
const automaton aut;
transposed_by_hand<const automaton> trh = { aut };
transposed_with_decltype<const automaton> trd = { aut };
}
My compilers complain that (G++ 4.9):
f.cc: In instantiation of 'struct transposed_with_decltype<const automaton>':
f.cc:44:49: required from here
f.cc:34:12: error: passing 'const automaton' as 'this' argument of 'void automaton::set_final()' discards qualifiers [-fpermissive]
auto set_final() -> decltype(aut.set_final())
^
and (Clang++ 3.3):
f.cc:42:23: error: default initialization of an object of const type 'const automaton' requires a user-provided default constructor
const automaton aut;
^
f.cc:34:36: error: member function 'set_final' not viable: 'this' argument has type 'const automaton', but function is not marked const
auto set_final() -> decltype(aut.set_final())
^~~
f.cc:44:49: note: in instantiation of template class 'transposed_with_decltype<const automaton>' requested here
transposed_with_decltype<const automaton> trd = { aut };
^
f.cc:6:12: note: 'set_final' declared here
void set_final() { final = true; }
^
2 errors generated.
And they are right! The expression in the decltype is breaking the const-ness of the wrapped automaton. Yet, I am not going to use this function, I swear. Just like I will not use the corresponding one wrapped by hand.
So my question is: is there a means to write the definition of the wrapping set_final so that I don't have to spell out its signature (input and output)? I have tried to use std::enable_if, but it changes nothing to the problem here. And anyway, it would need that the compiler be lazy, and accepts not to evaluate the second parameter of std::enable_if if it does not need to...
template <typename Aut>
struct transposed_with_decltype
{
Aut& aut;
auto get_final() const -> decltype(aut.get_final())
{
return aut.get_final();
}
auto set_final() -> typename std::enable_if<!std::is_const<Aut>::value,
decltype(aut.set_final())>::type
{
aut.set_final();
}
};
Thanks in advance.
I can get it to work (using GCC 4.6) just by using the advice Xeo mentions in his comment. That is, I turn the function into a trivial template, like so:
template<typename = void>
auto set_final() -> decltype(aut.set_final()) {
return aut.set_final();
}
== EDIT ==
Luc Danton comments below that a more recent GCC may reject the code, complaining that the decltype isn't dependent. I only have 4.6 here, but perhaps this could be worked around using something like this:
template<typename KLUDGE = int>
auto set_final() -> decltype((&aut+KLUDGE(0))->set_final()) {
return aut.set_final();
}
YMMV.
I'm building a large project on Debian 6.0.6 (with gcc 4.4.5) that was initially built in Microsoft VS (2008, I think).
What seems to be the problem is that when I declare a member as
typedef typename std::set<T>::iterator iterator, and then later use this iterator, gcc appears to interpret this as (const T*).
The part of the class containing the typename designation:
template <class entityType>
class entityArray
{
private: std::set<entityType> m_array;
public: typedef typename std::set<entityType>::iterator iterator;
...
public:
entityType* At( const char* name);
...
};
plus a few other classes that are needed for the discussion:
class entity
{
private:
entity* m_parent;
int m_ncid;
std::string m_name;
public:
entity () { m_ncid = 0; m_parent = NULL;}
virtual ~entity () {};
...
};
class attribute : public entity
{
public:
attribute(){};
virtual ~attribute(){};
};
class var : public entity
{
private:
entityArray<attribute> m_atts;
public:
var(){}
virtual ~var(){}
...
};
class dim : public entity
{
public:
dim() {};
virtual ~dim() {};
};
class group : public entity
{
private:
entityArray<var> m_vars;
entityArray<dim> m_dims;
...
public:
dim* DimAt( const char* dimname ) { return m_dims.At(dimname);}
};
Now an iterator is initialized through a call to the function DimAt which in turn calls At. The At function in the first class is defined as:
template <class entityType>
entityType* entityArray<entityType>::At( const char* name )
{
entityType dummy;
iterator iter;
entityType* ptr;
... define dummy ...
iter = m_array.find( dummy );
ptr = (iter != m_array.end()) ? &(*iter) : NULL;
return ptr;
}
Compiling the above produces
error: invalid conversion from const dim* to dim*., referring to &(*iter).
I realize that typename is required for declaring iterator, since the type is a dependent and qualified name, but I don't see why this substitution (const *) is being performed by the compiler. I would appreciate any help that you could provide. Thanks!
This has absolutely nothing to do with typename.
The standard allows std::set<T>::iterator and std::set<T>::const_iterator to be the same type, and with GCC the types are the same.
The reason is that modifying an element of a std::set e.g. by *iter = val might invalidate the ordering of the set elements, breaking the invariant that the elements of the set are always in order. By making the iterator type a constant iterator instead of a mutable iterator it's not possible to alter the element, preventing you from corrupting the set's ordering.
So with GCC's implementation, when you dereference the iterator using *iter you get a const entitType& and when you take its address using &*iter you get a const entityType*