In the following code, initialize() illustrates a method based on compile-time polymorphism. The version of initialize() compiled depends on int2type<true> and int2type<false>, only one of which will be true for a given template parameter T.
It just so happens that data member T* m_datum; will work for both int2type<true> and int2type<false>.
Now, I want to change the int2type<false> version to std::vector<T> m_datum;, so my question is, how do I modify my code so that the data member m_datum is polymorphic on int2type<>?
Note: please ignore the rationale behind the code below - instead, I would like to focus on the mechanics of achieving compile-time polymorphism for data members.
#include <type_traits>
#include <stdlib.h>
using namespace std;
template <bool n>
struct int2type
{
enum { value = n };
};
template< typename T >
struct is_trivially_copyable
{
static const bool value = std::is_standard_layout<T>::value;
};
template<class T>
class Foo
{
public:
Foo( size_t n ) : m_nr( n )
{
initialize( int2type<is_trivially_copyable<T>::value>() );
}
~Foo() { }
private:
void initialize( int2type<true> )
{
m_datum = (T*) calloc( sizeof(T), m_nr );
}
void initialize( int2type<false> )
{
m_datum = new T[m_nr];
}
private:
size_t m_nr;
T* m_datum; // ok for int2type<true>
// vector<T> m_datum; // want to change to this for int2type<false>
};
class Bar
{
public:
Bar() { }
virtual ~Bar() { }
};
int main(int argc, char** argv)
{
Foo<int> foo_trivial( 5 );
Foo<Bar> foo_nontrivial( 10 );
return 0;
}
C++11 solution, based on Nawaz's recommendations
#include <type_traits>
#include <vector>
#include <stdlib.h>
using namespace std;
template< typename T >
struct is_trivially_copyable
{
static const bool value = std::is_standard_layout<T>::value;
};
template<class T>
class Foo
{
private:
static const bool what = is_trivially_copyable<T>::value;
typedef typename std::conditional<what,T*,std::vector<T>>::type type;
public:
Foo( size_t n ) : m_nr( n )
{
initialize( m_datum );
}
~Foo() { }
private:
void initialize( T* dummy )
{
m_datum = (T*) calloc( sizeof(T), m_nr );
}
void initialize( std::vector<T>& dummy )
{
m_datum.resize( m_nr );
}
private:
size_t m_nr;
type m_datum;
};
class Bar
{
public:
Bar() { }
virtual ~Bar() { }
};
int main(int argc, char** argv)
{
Foo<int> foo_trivial( 5 );
Foo<Bar> foo_nontrivial( 10 );
return 0;
}
C++11 Solution
Use std::conditional as:
#include <type_traits>
template<class T>
class Foo
{
//some info we can use throughout the class
static const bool what = is_trivially_copyable<T>::value;
typedef typename std::conditional<what, T*, std::vector<T>>::type data_type;
//data members
data_type m_data; //this is what you need!
}
C++03 Solution
You can write a metafunction and partially specialize this as follows:
template<class T>
class Foo
{
//primary template
template<bool b, typename T>
struct get { typedef T* type; };
//partial specialization
template<typename T>
struct get<false, T> { typedef std::vector<T> type; };
//some info we can use throughout the class
static const bool what = is_trivially_copyable<T>::value;
typedef typename get<what, T>::type data_type;
//data members
data_type m_data; //this is what you need!
};
So when what is true, data_type will turn out to be T*, or else it will be std::vector<T>, as desired.
In either case, you don't need int2type class template. Just remove that from your code. You can write cleaner code, without it.
How about:
// Generic
template <typename T, typename Arg>
struct datum_type_dispatch {};
// Specialization for Arg = int2type<true>
template <typename T>
struct datum_type_dispatch<T, int2type<true> >
{
typedef T* type;
};
// Specialization for Arg = int2type<false>
template <typename T>
struct datum_type_dispatch<T, int2type<false> >
{
typedef std::vector<T> type;
};
template <typename T>
class Foo
{
// ...
private:
// Get the datum type based on int2type<...>
typedef typename datum_type_dispatch<T, int2type<is_trivially_copyable<T>::value> >::type datum_type;
datum_type m_datum;
};
Related
I am trying to understand the name lookup and argument dependency lookup.I have created a small example.
Edited:
https://godbolt.org/g/rMWUbe
#include <iostream>
void g(const int*) {}
template <typename T>
struct TypeResolution;
template <typename T>
struct TypeResolution<T&> {
typedef const T* type;
static constexpr void (*func_ptr)(TypeResolution::type) = g;
static constexpr void *func_ptr_void = (void*)func_ptr;
};
template <typename T>
struct TypeResolution {
typedef const T* type;
static constexpr void (*func_ptr)(TypeResolution::type) = g;
static constexpr void *func_ptr_void = (void*)func_ptr;
};
void foo_impl(void *[], void *[]) {
//Some work here, that will be in a different file or library
}
template <typename... ARGS>
void foo(ARGS && ... args) {
void *func_ptrs[] = { TypeResolution<ARGS>::func_ptr_void... };
void *args_ptrs[] = {(void*)&args...};
foo_impl(func_ptrs, args_ptrs);
}
struct MyClass {};
void g(const MyClass*) {}
int main(int argc, char* argv[]) {
int i = 1;
foo(i);
int j = 2;
foo(i, j);
MyClass c;
foo(c); //This fails.
}
So my question is, why it doesn't compile? Or more simply why the lookup of g inside the TypeResolution happens when the class is declared, and not when it is instantiated? As I expected inside the main function and then to see the function void g(const MyClass*)
What I want to obtain is to be able to call different functions for different different types, but without needing to forward declare them.
I am using g++ 5.4.0 on Ubuntu 16.04
template <typename T>
void foo(T t) {
void(*f)(T) = +[](T x){ return g(std::forward<T>(x)); };
f(t); //This compiles
g(t); //This compiles
}
this may be what you want. Note that the argument is moved once within f, which should not matter for primitive types.
template <class T>
struct TypeResolution;
template <class T>
struct TypeResolution<T&>:TypeResolution<T> {};
template <class T>
struct TypeResolution {
typedef const T* type;
static constexpr void (*func_ptr)(type) = +[](type x){ return g(x); };
static constexpr void *func_ptr_void = (void*)func_ptr;
};
requires c++17 because you cannot use lambdas in c++14 or c++11 in a constexpr expression.
In previous versions of C++ we can do:
template <class T>
struct TypeResolution {
typedef const T* type;
static void invoke_g(type t) { g( t ); }
static constexpr void (*func_ptr)(type) = invoke_g;
static constexpr void *func_ptr_void = (void*)func_ptr;
};
Based on Yakk's answer and based on n4487 I managed to implement a solution that I managed to compile with c++14.
https://godbolt.org/g/BRee4u
#include <iostream>
#include <type_traits>
#include <string>
void g(int*) {}
template <typename T>
struct TypeResolution;
template <typename T>
struct TypeResolution<T&> {
struct Inner {
static constexpr void foo(T* t) { g(t); }
};
static constexpr void *func_ptr_void = (void*)Inner::foo;
};
template <typename T>
struct TypeResolution {
struct Inner {
static constexpr void foo(T* t) { g(t); }
};
static constexpr void *func_ptr_void = (void*)Inner::foo;
};
void foo_impl(void *func_args[], void *data_args[]) {
//Some work here, that will be in a different file or library
}
template <typename... ARGS>
void foo(ARGS && ... args) {
void *func_ptrs[] = { TypeResolution<ARGS>::func_ptr_void... };
void *args_ptrs[] = {(void*)&args...};
foo_impl(func_ptrs, args_ptrs);
}
struct MyClass {};
void g(const MyClass*) {}
int main(int argc, char* argv[]) {
int i = 1;
foo(i);
MyClass c;
foo(c);
}
I have my Find method which I want to use both with shared and weak pointers. Live example
using namespace std;
template<typename value>
struct A
{
template < typename T, typename F >
T Find( F filterFunction)
{
for ( size_t i = 0; i < iteratableList.size(); i++)
{
auto castedTerrain = dynamic_pointer_cast<typename T::element_type>(iteratableList[i]);
if ( castedTerrain && filterFunction(castedTerrain) )
return iteratableList[i];
}
return T();
}
std::vector<value> iteratableList;
};
int main()
{
{
std::vector<std::shared_ptr<std::string>> names = { make_shared<std::string>("needle"), make_shared<std::string>("manyOtherNames") } ;
A<std::shared_ptr<std::string>> iterateable{ names };
iterateable.Find<std::shared_ptr<std::string>>([] ( std::shared_ptr<std::string> in ){ return *in == "needle";});
}
// When I use weak pointer my Find function fails.
//{
// std::vector<std::shared_ptr<std::string>> weakNames ;
// for ( auto elem : names )
// weakNames.push_back(elem)
// A<std::weak_ptr<std::string>> iterateable{ weakNames };
// iterateable.Find<std::weak_ptr<std::string>>([] ( std::weak_ptr<std::string> in ){ return *in == "needle";});
//}
}
I know I can do something like
std::is_same< std::weak_ptr ... > and use std::true_type and std::false_type but I am curious if there is a better and cleaner way to achieve avoid code duplication just for .lock() method.
Just have a template function you can use to obtain the "real" pointer. The specialization for std::shared_ptr just returns the argument:
template <typename T>
struct resolve_pointer;
template <typename T>
struct resolve_pointer<std::shared_ptr<T>>
{
static std::shared_ptr<T> resolve(std::shared_ptr<T> & p) const {
return p;
}
};
template <typename T>
struct resolve_pointer<std::weak_ptr<T>>
{
static std::shared_ptr<T> resolve(std::weak_ptr<T> & p) const {
return p.lock();
}
};
Now your Find function, in place of iteratableList[i], use resolve_pointer<T>::resolve(iteratableList[i]).
I'm a potato, an overloaded free function would work just as well and be a bit simpler to understand:
template <typename T>
std::shared_ptr<T> resolve_pointer(std::shared_ptr<T> & p) {
return p;
}
template <typename T>
std::shared_ptr<T> resolve_pointer(std::weak_ptr<T> & p) {
return p.lock();
}
If your goal is to be able to extend your code to provide interoperability with any strong/weak pointer pairs that have an implemented dynamic cast operation (shown here the std::strong/weak_ptr and boost::strong/weak_ptr), you can do this using a set of traits, like so... beware, dragons ahead:
// Defines a resolve static function to get a strong pointer from either
// a strong or a weak pointer.
template <typename T>
struct smart_pointer_info;
template <typename T>
struct smart_pointer_info<std::shared_ptr<T>>
{
typedef std::shared_ptr<T> ptr_type;
typedef T element_type;
typedef std::shared_ptr<T> resolved_type;
static resolved_type resolve(ptr_type & p) {
return p;
}
};
template <typename T>
struct smart_pointer_info<std::weak_ptr<T>>
{
typedef std::weak_ptr<T> ptr_type;
typedef T element_type;
typedef std::shared_ptr<T> resolved_type;
static resolved_type resolve(ptr_type & p) {
return p.lock();
}
};
template <typename T>
struct smart_pointer_info<boost::shared_ptr<T>>
{
typedef boost::shared_ptr<T> ptr_type;
typedef T element_type;
typedef boost::shared_ptr<T> resolved_type;
static resolved_type resolve(ptr_type & p) {
return p;
}
};
template <typename T>
struct smart_pointer_info<boost::weak_ptr<T>>
{
typedef boost::weak_ptr<T> ptr_type;
typedef T element_type;
typedef boost::shared_ptr<T> resolved_type;
static resolved_type resolve(ptr_type & p) {
return p.lock();
}
};
// Provides a static "cast" function that converts a strong pointer T
// into a strong point that points at an object of type D.
template <typename T, typename D>
struct smart_pointer_dynamic_cast;
template <typename T, typename D>
struct smart_pointer_dynamic_cast<std::shared_ptr<T>, D>
{
typedef std::shared_ptr<T> ptr_type;
typedef std::shared_ptr<D> cast_type;
static cast_type cast(ptr_type & p) {
return std::dynamic_pointer_cast<D>(p);
}
};
template <typename T, typename D>
struct smart_pointer_dynamic_cast<boost::shared_ptr<T>, D>
{
typedef boost::shared_ptr<T> ptr_type;
typedef boost::shared_ptr<D> cast_type;
static cast_type cast(ptr_type & p) {
return boost::dynamic_pointer_cast<D>(p);
}
};
// Helper so we can omit the template parameter for the source pointer type.
template <typename D>
struct dynamic_cast_helper
{
template <typename P>
static typename smart_pointer_dynamic_cast<typename smart_pointer_info<P>::resolved_type, D>::cast_type cast(P & p) {
typename smart_pointer_info<P>::resolved_type r = smart_pointer_info<P>::resolve(p);
return smart_pointer_dynamic_cast<typename smart_pointer_info<P>::resolved_type, D>::cast(r);
}
};
// Then we might use it like so:
class A {
public:
virtual void print() {
std::cout << "A::print()" << std::endl;
}
};
class B : public A {
public:
virtual void print() {
std::cout << "B::print()" << std::endl;
}
};
int main()
{
auto x = std::make_shared<B>();
std::weak_ptr<B> xw{x};
auto y = boost::make_shared<B>();
boost::weak_ptr<B> yw{y};
dynamic_cast_helper<A>::cast(x)->print();
dynamic_cast_helper<A>::cast(xw)->print();
dynamic_cast_helper<A>::cast(y)->print();
dynamic_cast_helper<A>::cast(yw)->print();
return 0;
}
(Demo)
Your cast dynamic_pointer_cast<typename T::element_type>(iteratableList[i]) then becomes dynamic_cast_helper<typename smart_pointer_info<T>::element_type>::cast(iteratableList[i]) and all the types along the way get inferred by the compiler.
I want to be able to get the size of polymorphic object. At the moment I got this:
struct Base {
virtual std::size_t size() const {
return sizeof(*this);
}
};
struct Derived : Base {
virtual std::size_t size() const {
return sizeof(*this);
}
};
Which is literally copy & paste. I want to do better. Suppose I really hate macros and CRTP seems like the only sensible approach. Let us give it a try:
struct SizedBase {
virtual std::size_t size() const = 0;
};
template <typename Type>
struct Sized : virtual SizedBase {
std::size_t size() const override {
return sizeof(Type);
}
};
struct Base : Sized<Base> {};
struct Derived : Base, Sized<Derived> {};
This looks much better, but sadly is ill-formed: Derived contains two final overriders for size() from Base and from Sized<Derived>. We can solve this by inheriting through Sized:
struct SizedBase {
virtual std::size_t size() const = 0;
};
template <typename Type, typename... SizedBases>
struct Sized : virtual SizedBase, SizedBases... {
std::size_t size() const override {
return sizeof(Type);
}
};
struct Base : Sized<Base> {};
struct Derived : Sized<Derived, Base> {};
This works as intended, however gets somewhat confusing in the event of multiple inheritance and prohibits altering accessibility/virtualness of bases.
So, is there a better way?
Not that anyone should really use this, but...
template <typename>
struct None1 {};
template <typename>
struct None2 {};
template <typename T>
struct PrivateBase { using Tpriv = T; using Tprot = None1<T>; using Tpub = None2<T>; };
template <typename T>
struct ProtectedBase { using Tpriv = None1<T>; using Tprot = T; using Tpub = None2<T>; };
template <typename T>
struct PublicBase { using Tpriv = None1<T>; using Tprot = None2<T>; using Tpub = T; };
template <typename K>
struct TriBase : private K::Tpriv, protected K::Tprot, public K::Tpub {};
template <typename T, typename ... Bases>
struct Sized : private Bases::Tpriv..., protected Bases::Tprot..., public Bases::Tpub...
{
virtual size_t size() { return sizeof(T); }
};
struct Foo : Sized<Foo> {};
struct X{};
struct Y{};
struct Bar : Sized<Bar, PrivateBase<X>, ProtectedBase<Y>, PublicBase<Foo>> {};
int main ()
{
Bar b;
Foo* f = &b;
X* x = &b; // error : private base
Y* y = &b; // error : protected base
}
Virtual inheritance is left as an exercise to the reader.
The order of base classes is not preserved, but you should not depend on it anyway.
Something that is a little bit more production-friendly can be implemented like this (this is a rough sketch):
#include <cstdlib>
#include <typeinfo>
#include <unordered_map>
#include <memory>
#include <iostream>
struct myinfo
{
size_t size;
// any other stuff
};
using TypeInfoRef = std::reference_wrapper<const std::type_info>;
struct Hasher
{
std::size_t operator()(TypeInfoRef code) const
{
return code.get().hash_code();
}
};
struct EqualTo
{
bool operator()(TypeInfoRef lhs, TypeInfoRef rhs) const
{
return lhs.get() == rhs.get();
}
};
static std::unordered_map<TypeInfoRef, myinfo, Hasher, EqualTo> typemap;
template <typename K>
struct typemap_initializer
{
typemap_initializer()
{
typemap[typeid(K)] = myinfo{sizeof(K)};
}
};
struct Base
{
virtual ~Base() {}
size_t size() { return typemap[typeid(*this)].size; }
template<typename K, typename... Arg>
friend K* alloc(Arg...);
private:
void* operator new(size_t sz) { return ::operator new(sz); }
};
template<typename K, typename... Arg>
K* alloc(Arg... arg)
{
static typemap_initializer<K> ti;
return new K(arg...);
}
struct Foo : Base {int a;};
struct Bar : Foo {int b; int c;};
int main ()
{
Foo* f = alloc<Foo>();
Bar* g = alloc<Bar>();
std::cout << f->size() << std::endl;
std::cout << g->size() << std::endl;
}
Of course one gives up the familiar Foo* foo = new Foo syntax, but in the era of ubiquitous std::make_shared<> this is not a big problem.
I have a templated class with variable numbers of templated arguments. As in these cases (I cannot afford C++11) a good practice is to create a default class that we call none and put it as default like below.
struct none {};
template<class T1=none, T2=none, T3=none>
class A{
template<class T>
double extract() { return none();}
template<>
double extract<T1>() { return m1_();}
template<>
double extract<T2>() { return m2_();}
template<>
double extract<T3> () { return m3_();}
T1 m1_;
T2 m2_;
T3 m3_;
};
At this stage I don't know how to implement a generic/templated accessor function that can access each of the templated argument.
All of the templated arguments are different so I specialized A::extract() for each of the templated arguments.
Is there any better way to do this? Any sort of tagging I can have a look at?
struct none {};
template <class T, class N>
class Holder : public N
{
protected:
T m;
typedef Holder<T, N> First;
double extractP(T*) { return m(); }
template <class X> double extractP(X*) {
return this->N::extractP(static_cast<X*>(0));
}
};
template <class T>
class Holder<T, none>
{
protected:
T m;
typedef Holder<T, none> First;
double extractP(T*) { return m(); }
template <class X> none extractP(X*) {
return none();
}
};
template <class T1 = none, class T2 = none, class T3 = none>
class A : Holder<T1, Holder<T2, Holder<T3, none> > >
{
public:
template <class T> double extract() {
return this->extractP(static_cast<T*>(0));
}
};
A similarly-named solution to n.m but more on the Boost's Variant class design.
The suggestion is to use a Variant container (a generic container for your objects) and use accessors directly on them.
#include <iostream>
#include <stdexcept>
using namespace std;
class BaseHolder
{
public:
virtual ~BaseHolder(){}
virtual BaseHolder* clone() const = 0;
};
template<typename T>
class HoldData : public BaseHolder
{
public:
HoldData(const T& t_) : t(t_){}
virtual BaseHolder* clone() const {
return new HoldData<T>(t);
}
T getData() {
return t;
}
private:
T t;
};
class Variant
{
public:
Variant() : data(0) {}
template<typename T>
Variant(const T& t) : data(new HoldData<T>(t)){}
Variant(const Variant& other) : data(other.data ? other.data->clone() : 0) {}
~Variant(){delete data;}
template<typename T>
T getData() {
return ((HoldData<T>*)data)->getData();
}
private:
BaseHolder* data;
private:
Variant& operator=(const Variant& other) { return *this;} // Not allowed
};
struct none {};
class Container{
public:
Container() : m1_(0), m2_(0), m3_(0){}
~Container() {
if(m1_)
delete m1_;
if(m2_)
delete m1_;
if(m3_)
delete m1_;
}
none extract() { return none();}
template<typename T>
void insertM1(T obj) {
m1_ = new Variant(obj);
}
template<typename T>
T extractM1() {
if(m1_ != 0)
return m1_->getData<T>();
else
throw std::runtime_error("Element not set");
}
// TODO: implement m2 and m3
Variant *m1_;
Variant *m2_;
Variant *m3_;
};
int main() {
Container obj;
char M1 = 'Z';
obj.insertM1(M1);
char extractedM1 = obj.extractM1<char>();
cout << extractedM1;
return 0;
}
http://ideone.com/BaCWSV
Your class seems to mimic std::tuple, which, unfortunately for you, was added in C++11. The good news is that you can use boost::tuple instead.
As an example of usage:
boost::tuple<std::string, double> t = boost::make_tuple("John Doe", 4.815162342);
std::cout << boost::get<0>(t) << '\n';
std::cout << boost::get<1>(t) << '\n';
Live demo
Without access to C++11, it's a bit uglier, but you can leverage Boost.Tuple:
#include <iostream>
#include <boost/tuple/tuple.hpp>
template <size_t I, typename T, typename U>
struct AccessImpl;
template <size_t I, typename T, typename U>
struct AccessImpl {
template <typename Tuple>
static T& impl(Tuple& tuple) {
typedef typename ::boost::tuples::element<I+1, Tuple>::type Next;
return AccessImpl<I+1, T, Next>::impl(tuple);
}
};
template <size_t I, typename T>
struct AccessImpl<I, T, T> {
template <typename Tuple>
static T& impl(Tuple& tuple) { return boost::get<I>(tuple); }
};
template <typename T, typename Tuple>
T& access(Tuple& tuple) {
typedef typename ::boost::tuples::element<0, Tuple>::type Head;
return AccessImpl<0, T, Head>::impl(tuple);
}
int main() {
boost::tuples::tuple<char, int, std::string> example('a', 1, "Hello, World!");
std::cout << access<std::string>(example) << "\n";
return 0;
}
This, as expected, prints "Hello, World!".
template <typename T, typename C>
class CSVWriter{
template <typename PrinterT>
void write(std::ostream& stream, const PrinterT& printer){
}
};
I want to check whether there exists at least two overloads PrinterT::operator()(T*) and PrinterT::operator()(C*)
PrinterT may or may not inherit from std::unary_function
What concept Checking Classes I need to use here ?
(I am not using C++11)
You can use something like that
#include <iostream>
#include <boost/concept/requires.hpp>
#include <boost/concept/usage.hpp>
template <class Type, class Param>
class has_operator_round_brackets_with_parameter
{
public:
BOOST_CONCEPT_USAGE(has_operator_round_brackets_with_parameter)
{
_t(_p);
}
private:
Type _t;
Param _p;
};
struct X {};
struct Y {};
struct Test1
{
void operator() (X*) const { }
};
struct Test2: public Test1
{
void operator() (X*) const { }
void operator() (Y*) const { }
};
template <class T, class C>
struct CSVWriter
{
template <class PrinterT>
BOOST_CONCEPT_REQUIRES(
((has_operator_round_brackets_with_parameter<PrinterT, T*>))
((has_operator_round_brackets_with_parameter<PrinterT, C*>)),
(void)) write(std::ostream& stream, const PrinterT& printer)
{
}
};
int main()
{
CSVWriter<X, Y> w;
// w.write<Test1>(std::cout, Test1()); // FAIL
w.write<Test2>(std::cout, Test2()); // OK
return 0;
}