I have a template class like this:
template<T>
class MyClass
{
T* data;
}
Sometimes, I want to use the class with a constant type T as follows:
MyClass<const MyObject> mci;
but I want to modify the data using const_cast<MyObject*>data (it is not important why but MyClass is a reference count smart pointer class which keeps the reference count in the data itself. MyObject is derived from some type which contains the count.
The data should not be modified but the count must be modified by the smart pointer.).
Is there a way to remove const-ness from T? Fictional code:
const_cast<unconst T>(data)
?
The simplest way here would be to make the reference count mutable.
However, if you are interested in how it would work with the const_cast, then reimplementing boost's remove_const should be quite simple:
template <class T>
struct RemoveConst
{
typedef T type;
};
template <class T>
struct RemoveConst<const T>
{
typedef T type;
};
const_cast<typename RemoveConst<T>::type*>(t)->inc();
You have the answer. const_cast works in both directions:
char* a;
const char* b;
a = const_cast<char*>(b);
b = const_cast<const char*>(a); // not strictly necessarily, just here for illustration
As for you specific issue, have you considered the mutable keyword? It allows a member variable to be modified inside a const method.
class foo {
mutable int x;
public:
inc_when_const() const { ++x; }
dec_when_const() const { --x; }
};
Make the reference count mutable in the class managed by your intrusive pointer. This is entirely reasonable, and reflects "logical constness" exactly correctly -- i.e. changing the object's reference count does not reflect any change in the state of the object itself. In other words, the reference count isn't logically part of the object -- the object just happens to be a convenient place to store this semi-unrelated data.
If you can use Boost, the Type Traits library provides the remove_const metafunction that does that.
Here is my C++11 unconst function template.
If you use it, you are flirting with undefined behavior. You have been warned.
// on Ubuntu (and probably others) compile and test with
// g++ -std=c++11 test.c && ./a.out ; echo $?
template < class T > T & unconst ( T const & t ) {
return const_cast < T & > ( t ) ;
}
// demonstration of use
struct {
const int n = 4;
} s;
int main () {
unconst ( s.n ) = 5;
return s.n;
}
Related
Having returned relatively recently to C++ after decades of Java, I am currently struggling with a template-based approach to data conversion for instances where type erasure has been applied. Please bear with me, my nomenclature may still be off for C++-natives.
This is what I am trying to achieve:
Implement dynamic variables which are able to hold essentially any value type
Access the content of those variables using various other representations (string, ints, binary, ...)
Be able to hold variable instances in containers, independent of their value type
Convert between variable value and representation using conversion functions
Be able to introduce new representations just by providing new conversion functions
Constraints: use only C++-11 features if possible, no use of libraries like boost::any etc.
A rough sketch of this might look like this:
#include <iostream>
#include <vector>
void convert(const std::string &f, std::string &t) { t = f; }
void convert(const int &f, std::string &t) { t = std::to_string(f); }
void convert(const std::string &f, int &t) { t = std::stoi(f); }
void convert(const int &f, int &t) { t = f; }
struct Variable {
virtual void get(int &i) = 0;
virtual void get(std::string &s) = 0;
};
template <typename T> struct VariableImpl : Variable {
T value;
VariableImpl(const T &v) : value{v} {};
void get(int &i) { convert(value, i); };
void get(std::string &s) { convert(value, s); };
};
int main() {
VariableImpl<int> v1{42};
VariableImpl<std::string> v2{"1234"};
std::vector<Variable *> vars{&v1, &v2};
for (auto &v : vars) {
int i;
v->get(i);
std::string s;
v->get(s);
std::cout << "int representation: " << i <<
", string representation: " << s << std::endl;
}
return 0;
}
The code does what it is supposed to do, but obvoiusly I would like to get rid of Variable::get(int/std::string/...) and instead template them, because otherwise every new representation requires a definition and an implementation with the latter being exactly the same as all the others.
I've played with various approaches so far, like virtual templated, methods, applying the CRDT with intermediate type, various forms of wrappers, yet in all of them I get bitten by the erased value type of VariableImpl. On one hand, I think there might not be a solution, because after type erasure, the compiler cannot possibly know what templated getters and converter calls it must generate. On the other hand I think i might be missing something really essential here and there should be a solution despite the constraints mentioned above.
This is a classical double dispatch problem. The usual solution to this problem is to have some kind of dispatcher class with multiple implementations of the function you want to dispatch (get in your case). This is called the visitor pattern. The well-known drawback of it is the dependency cycle it creates (each class in the hierarchy depends on all other classes in the hierarchy). Thus there's a need to revisit it each time a new type is added. No amount of template wizardry eliminates it.
You don't have a specialised Visitor class, your Variable serves as a Visitor of itself, but this is a minor detail.
Since you don't like this solution, there is another one. It uses a registry of functions populated at run time and keyed on type identification of their arguments. This is sometimes called "Acyclic Visitor".
Here's a half-baked C++11-friendly implementation for your case.
#include <map>
#include <vector>
#include <typeinfo>
#include <typeindex>
#include <utility>
#include <functional>
#include <string>
#include <stdexcept>
struct Variable
{
virtual void convertValue(Variable& to) const = 0;
virtual ~Variable() {};
virtual std::type_index getTypeIdx() const = 0;
template <typename K> K get() const;
static std::map<std::pair<std::type_index, std::type_index>,
std::function<void(const Variable&, Variable&)>>
conversionMap;
template <typename T, typename K>
static void registerConversion(K (*fn)(const T&));
};
template <typename T>
struct VariableImpl : Variable
{
T value;
VariableImpl(const T &v) : value{v} {};
VariableImpl() : value{} {}; // this is needed for a declaration of
// `VariableImpl<K> below
// It can be avoided but it is
// a story for another day
void convertValue(Variable& to) const override
{
auto typeIdxFrom = getTypeIdx();
auto typeIdxTo = to.getTypeIdx();
if (typeIdxFrom == typeIdxTo) // no conversion needed
{
dynamic_cast<VariableImpl<T>&>(to).value = value;
}
else
{
auto fcnIter = conversionMap.find({getTypeIdx(), to.getTypeIdx()});
if (fcnIter != conversionMap.end())
{
fcnIter->second(*this, to);
}
else
throw std::logic_error("no conversion");
}
}
std::type_index getTypeIdx() const override
{
return std::type_index(typeid(T));
}
};
template <typename K> K Variable::get() const
{
VariableImpl<K> vk;
convertValue(vk);
return vk.value;
}
template <typename T, typename K>
void Variable::registerConversion(K (*fn)(const T&))
{
// add a mutex if you ever spread this over multiple threads
conversionMap[{std::type_index(typeid(T)), std::type_index(typeid(K))}] =
[fn](const Variable& from, Variable& to) {
dynamic_cast<VariableImpl<K>&>(to).value =
fn(dynamic_cast<const VariableImpl<T>&>(from).value);
};
}
Now of course you need to call registerConversion e.g. at the beginning of main and pass it each conversion function.
Variable::registerConversion(int_to_string);
Variable::registerConversion(string_to_int);
This is not ideal, but hardly anything is ever ideal.
Having said all that, I would recommend you revisit your design. Do you really need all these conversions? Why not pick one representation and stick with it?
Implement dynamic variables which are able to hold essentially any value type
Be able to hold variable instances in containers, independent of their value type
These two requirements are quite challenging on its own. The class templates don't really encourage inheritance, and you already did the right thing to hold what you asked for: introduced a common base class for the class template, which you can later refer to in order to store pointers of the said type in a collection.
Access the content of those variables using various other representations (string, ints, binary, ...)
Be able to introduce new representations just by providing new conversion functions
This is where it breaks. Function templates assume common implementation for different types, while inheritance assumes different implementation for the same types.
You goal is to introduce different implementation for different types, and in order to make your requirements viable you have to switch to one of those two options instead (or put up with a number of functions for each case which you have already introduced yourself)
Edit:
One of the strategies you may employ to enforce inheritance approach is generalisation of the arguments to the extent where they can be used interchangeably by the abstract interface. E.g. you may wrap the converting arguments inside of a union like this:
struct Variable {
struct converter_type {
enum { INT, STRING } type;
union {
int* m_int;
std::string* m_string;
};
};
virtual void get(converter_type& var) = 0;
virtual ~Variable() = default;
};
And then take whatever part of it inside of the implementation:
void get(converter_type& var) override {
switch (var.type) {
case converter_type::INT:
convert(value, var.m_int);
break;
case converter_type::STRING:
convert(value, var.m_string);
break;
}
}
To be honest I don't think this is a less verbose approach compared to just having a number of functions for each type combination, but i think you got the idea that you can just wrap your arguments somehow to cement the abstract class interface.
Implement std::any. It is similar to boost::any.
Create a conversion dispatcher based off typeids. Store your any alongside the conversion dispatcher.
"new conversion functions" have to be passed to the dispatcher.
When asked to convert to a type, pass that typeid to the dispatcher.
So we start with these 3 types:
using any = std::any; // implement this
using converter = std::function<any(any const&)>;
using convert_table = std::map<std::type_index, converter>;
using convert_lookup = convert_table(*)();
template<class T>
convert_table& lookup_convert_table() {
static convert_table t;
return t;
}
struct converter_any: any {
template<class T,
typename std::enable_if<
!std::is_same<typename std::decay<T>::type, converter_any>::value, bool
>::type = true
>
converter_any( T&& t ):
any(std::forward<T>(t)),
table(&lookup_convert_table<typename std::decay<T>::type>())
{}
converter_any(converter_any const&)=default;
converter_any(converter_any &&)=default;
converter_any& operator=(converter_any const&)=default;
converter_any& operator=(converter_any&&)=default;
~converter_any()=default;
converter_any()=default;
convert_table const* table = nullptr;
template<class U>
U convert_to() const {
if (!table)
throw 1; // make a better exception than int
auto it = table->find(typeid(U));
if (it == table->end())
throw 2; // make a better exception than int
any const& self = *this;
return any_cast<U>((it->second)(self));
}
};
template<class Dest, class Src>
bool add_converter_to_table( Dest(*f)(Src const&) ) {
lookup_convert_table<Src>()[typeid(Dest)] = [f](any const& s)->any {
Src src = std::any_cast<Src>(s);
auto r = f(src);
return r;
};
return true;
}
now your code looks like:
const bool bStringRegistered =
add_converter_to_table(+[](std::string const& f)->std::string{ return f; })
&& add_converter_to_table(+[](std::string const& f)->int{ return std::stoi(f); });
const bool bIntRegistered =
add_converter_to_table(+[](int const& i)->int{ return i; })
&& add_converter_to_table(+[](int const& i)->std::string{ return std::to_string(i); });
int main() {
converter_any v1{42};
converter_any v2{std::string("1234")};
std::vector<converter_any> vars{v1, v2}; // copies!
for (auto &v : vars) {
int i = v.convert_to<int>();
std::string s = v.convert_to<std::string>();
std::cout << "int representation: " << i <<
", string representation: " << s << std::endl;
}
}
live example.
...
Ok, what did I do?
I used any to be a smart void* that can store anything. Rewriting this is a bad idea, use someone else's implementation.
Then, I augmented it with a manually written virtual function table. Which table I add is determined by the constructor of my converter_any; here, I know the type stored, so I can store the right table.
Typically when using this technique, I'd know what functions are in there. For your implementation we do not; so the table is a map from the type id of the destination, to a conversion function.
The conversion function takes anys and returns anys -- again, don't repeat this work. And now it has a fixed signature.
To add support for a type, you independently register conversion functions. Here, my conversion function registration helper deduces the from type (to determine which table to register it in) and the destination type (to determine which entry in the table), and then automatically writes the any boxing/unboxing code for you.
...
At a higher level, what I'm doing is writing my own type erasure and object model. C++ has enough power that you can write your own object models, and when you want features that the default object model doesn't solve, well, roll a new object model.
Second, I'm using value types. A Java programmer isn't used to value types having polymorphic behavior, but much of C++ works much better if you write your code using value types.
So my converter_any is a polymorphic value type. You can store copies of them in vectors etc, and it just works.
I have a class that can take both a non-const pointer or a const pointer as arguments to its overloaded constructors. In my particular case, I need to instantiate an object of this class from both const and non-const methods of class T, but it fails from const methods, as it can't assign the const pointer to foo .
myClass() {
public:
myClass(T* v);
myClass(const T* v);
// ...
T* foo;
// ...
}
Is it possible to assign the argument in both constructors to foo? If so, what would be the correct syntax?
EDIT:
In a more specific case, I have a class myClass that wraps around std::vector and allows to me to directly access subsets of a vector through a nested class mySubset:
template<typename _type>
myClass() {
std::vector<_type> data;
public:
class mySubset(){
myClass<type>* foo;
public:
mySubset(myClass<_type>* _in) { foo = _in; };
mySubset(const myClass<_type>* _in) { foo = _in; /* error */ };
// ...
}
// ...
myClass();
// ...
void mySubset method() { return mySubset(this); };;
void mySubset const_method const() { return mySubset(this); /* error */ };
// ...
}
The code within is irrelevant -basically mySubset allows to both read and write to specific vector positions. While I'm able to achieve what I want with separate const and non-const nested classes, I was looking for a way to do this with a single return type.
I think you'll have to reconsider your design since you can't initialize a T* with a const T* lvalue, without const_cast which should be avoided unless you're really really sure, (since it invokes an undefined behavior if you try to modify a const pointer after casting away its constness)
Instead, you could use template type deduction for const and non const
template <typename T>
class myClass {
public:
//myClass(T* v):foo(v) { }
myClass( T* v):foo(v)
{
}
// ...
T* foo;
// ...
};
Then,
int a =42;
const int* p1 = &a;
int *p2 = &a;
myClass X1(p1); //C++17 auto type deduction or use myClass<const int> X1(p1)
myClass X2(p2);
You could using const_cast in your const T* constructor, but typically you shouldn't.
const T* means "point to a constant value T", and you store a "pointer to a T". If you do a const cast, you could end up modifying a value which shouldn't be modified. If you aren't going to modify foo, just declare it const T* and just use the single const T* constructor.
I'd check to see if this is a design issue. A lot of the times these scenarios appear:
(1) Where you're storing a pointer to something as non-const when it should be const. Typically this is because you're accessing values in another object and you should be passing the object as a (possibly const) reference at each use site rather than storing a pointer to it.
(2) When you really want to store a copy of an object, in which case you just keep a regular T and pass it in as const T& in the constructor.
(3) You're dealing with raw C-style strings and want to copy the contents into your own buffer.
If you don't want to use parameterized-type (template) class as #P0W's answer, it is not possible you can use only one pointer to accept all constant and non-constant pointer type. You need another constant pointer type to accept only const <your another class> * in your wrapper class.
Below code works after you have two separate pointer types in wrapper class which you may not like.
#include <iostream>
using namespace std;
class SomeObject {
public:
SomeObject(){}
explicit SomeObject(int i):testVal(i){}
private:
int testVal;
};
class PtWrapper {
public:
PtWrapper(SomeObject *pso);
PtWrapper(const SomeObject *cpso);
private:
SomeObject *pSO;
const SomeObject *cpSO;
};
int main(int argc, char *argv[]) {
SomeObject so(133);
SomeObject *pso = &so;
const SomeObject cso(166);
const SomeObject *cpso = &cso;
PtWrapper pw1(pso);
PtWrapper pw2(cpso);
return 0;
}
PtWrapper::PtWrapper(SomeObject *pso) :pSO(pso){
}
PtWrapper::PtWrapper(const SomeObject *cpso):cpSO(cpso){}
I'm wondering how "this" pointer is being passed to the methods from the class.
Let's see this snippet of code:
class CTest
{
public:
CTest(int n_) : n(n_) {}
void method()
{
std::cout << n << std::endl;
}
private:
int n;
};
int main()
{
CTest t1(100);
boost::bind(&CTest::method, &t1)(); //100
boost::bind(&CTest::method, _1)(&t1); //100
Test::method(&t1); //no matching function for call to ‘CTest::method(CTest*)’
return 0;
}
Assuming the bind works just like a function object, it passes this/object pointer somehow. If I want to do it explicitly I get an compilation error.
How does it work in fact?
boost::bind recognises when the target it wraps is a pointer to member, and uses a different code path that calls it using the right syntax for a pointer to member.
Like most problems in programming, you can solve it by adding a level of indirection. bind can apply a transformation to its target so that a pointer to member will be adapted into something that can be called like a normal function object, and takes care of the details, so bind itself doesn't need to know the details.
The function boost::mem_fn can be used to transform a pointer to member into a callable object:
void (CTest::*memptr)() = &CTest::method;
CTest* p = &t1;
auto callable = boost::mem_fn(memptr);
callable(p); // calls (p.->*memptr)()
So given that adaptor, bind only needs to ensure it is used whenever needed.
In the GCC implementation we have something like this:
template<class T>
struct maybe_wrap_mem_ptr
{
typedef T type;
};
// partial specialization for pointer to member
template<class R, class C>
struct maybe_wrap_mem_ptr<R C::*>
{
typedef mem_fn_wrapper<R C::*> type;
};
template<class T>
typename maybe_wrap_mem_ptr<T>::type
wrap_mem_ptr(T t)
{ return typename maybe_wrap_mem_ptr<T>::type(t); }
Where mem_fn_wrapper is the type returned by the std::mem_fn function. So bind can just use wrap_mem_ptr to ensure that the object it wraps can be called uniformly.
Say I have a struct with a bunch of members:
struct foo {
int len;
bar *stuff;
};
As it so happens stuff will point to an array of bars that is len long. I'd like to encode this in stuff's type. So something like:
struct foo {
int len;
DependentLength<bar, &foo::len> stuff;
};
Then I could implement DependentLength to behave like a pointer to a bar array but that asserts when trying to looking at an index bigger than foo::len. However, I can't implement DependentLength<&foo::len>::operator[] because operator[] only takes one parameter, the index, and it needs to know the location of the 'foo' object in order to dereference the member pointer template parameter and do the assert check.
However, I happen to know that DependentLength will only ever be used here as a member of 'foo'. What I'd really like to do is tell DependentLength where to find len relative to itself, rather than relative to a foo pointer. So something like DependentLength<(char*)&foo::stuff - (char*)&foo::len> stuff;, but that's not legal C++. Is there a good or failing that evil language hack that could make this work?
So something like DependentLength<(char*)&foo::stuff - (char*)&foo::len> stuff;
You're asking templates to perform calculations based on dynamic properties passed to them during run-time ... that won't work for templates since they must be instantiated with values that allow the compile to create the code requested by the template parameters at compile time. Thus any values passed to a template must be resolvable at compile-time, and not run-time.
You're going to have to use a dynamic container type. For instance, std::vector meets your request where the std::vector::at() function will throw an exception if you exceed the bounds of the underlying container. It's unfortunately not as convenient as a static_assert, but again, using static_assert is impossible for this situation since you need run-time checking for the bounds. Additionally, std::vector also incorporates an overload for operator[], iterators, queries for it's size, etc.
You can tell the template the offset of the member to use as length.
template<typename T, typename LEN_T, ptrdiff_t LEN_OFFSET>
class DependentArray
{
public:
T& operator[](LEN_T i_offset)
{
if (i_offset < 0) throw xxx;
if (i_offset > this->size()) throw xxx;
return this->m_pArr[i_offset];
} // []
private:
LEN_T& size()
{
return *reinterpret_cast<LEN_T*>(reinterpret_cast<char*>(this) + LEN_OFFSET);
} // ()
private:
T* m_pArr;
};
struct foo
{
int len;
DependentArray<bar, int, -sizeof(int)> stuff;
};
Edit 2:
Thought of another solution. Use a class that is good for foo only to supply the offset of the size field and define its method after foo is defined and offsets can be calculated:
#define MEMBER_OFFSET(T,M) \
(reinterpret_cast<char*>(&reinterpret_cast<T*>(0x10)->M) - \
reinterpret_cast<char*>(reinterpret_cast<T*>(0x10)))
template<typename T, typename LEN_T, typename SIZE_OFFSET_SUPPLIER>
class FooDependentArray
{
public:
T& operator[](LEN_T i_offset)
{
if (i_offset < 0) throw xxx;
if (i_offset > this->size()) throw xxx;
return this->m_pArr[i_offset];
} // []
private:
LEN_T& size()
{
const ptrdiff_t len_offest = SIZE_OFFSET_SUPPLIER::getOffset();
return *reinterpret_cast<LEN_T*>(reinterpret_cast<char*>(this) + len_offset);
} // ()
private:
T* m_pArr;
};
struct FooSizeOffsetSupplier
{
static ptrdiff_t getOffset();
};
struct foo
{
int len;
DependentArray<bar, int, FooSizeOffsetSupplier> stuff;
};
ptrdiff_t FooSizeOffsetSupplier::getOffset()
{
return MEMBER_OFFSET(Foo,m_len) - MEMBER_OFFSET(Foo,m_pArr);
} // ()
This makes it possible to add and remove members from foo.
There is some class which have methods like:
int getSomething1();
std::string getSomething2();
someClass getSomething3();
There is structure which describes fields of this class like:
{"name of field", pointer to getter, std::type_info}
Then I would like to use it as follows:
if(type == int){
field_int = (int)getter();
}
else if(type == std::string){
field_string = (std::string)getter();
}
etc.
How to transform getters like
int getSomething1();
std::string getSomething2();
etc.
to some universal function pointer and then to get the correct value of field?
This answer of mine to another question addresses your problem pretty well. With some minor modifications, you get this:
template<class C, class T>
T get_attribute(const C& instance, T (C::*func)() const) {
return (instance.*func)();
}
Assuming the following:
struct Foo {
int getSomething1() const;
std::string getSomething2() const;
someClass getSomething3() const;
};
You can use it like this:
Foo foo;
int value = get_attribute<Foo, int>(foo, &Foo::getSomething1);
std::string value = get_attribute<Foo, std::string>(foo, &Foo::getSomething2);
someClass value = get_attribute<Foo, someClass>(foo, &Foo::getSomething3);
You can of course transform get_attribute to a functor to bind some or all of the arguments.
There is no formal universal function pointer, the equivalent of void*
for data. The usual solution is to use void (*)(); you are guaranteed
that you can convert any (non-member) function pointer to this (or any
other function pointer type) and back without loss of information.
If there is a certain similarity in the function signatures (e.g. all
are getters, with no arguments) and how they are used, it may be
possible to handle this with an abstract base class and a set of derived
classes (possibly templated); putting pointers to instances of these
classes in a map would definitely be more elegant than an enormous
switch.
What you are trying to achieve can be better achieved with already existing containers such as a boost fusion sequence. I'd advice that you try this first.
Templates to the rescue!
// Create mapping of type to specific function
template <typename T> T getSomething(); // No default implementation
template <> int getSomething<int>() { return getSomething1(); }
template <> std::string getSomething<std::string>() { return getSomething2(); }
template <> someClass getSomething<someClass>() { return getSomething3(); }
// Convenience wrapper
template <typename T> void getSomething(T& t) { t = getSomething<T>(); }
// Use
int i = getSomething<int>();
std::string s;
getSomething(s);
As I understand, your difficulty is in storing the function pointers, since they are of different types. You can solve this using Boost.Any and Boost.Function.
#include <boost/any.hpp>
#include <boost/function.hpp>
int getInt() {
return 0;
}
std::string getString() {
return "hello";
}
int main()
{
boost::function<boost::any ()> intFunc(getInt);
boost::function<boost::any ()> strFunc(getString);
int i = boost::any_cast<int>(intFunc());
std::string str = boost::any_cast<std::string>(strFunc());
}