I have following example:
struct Wrapper
{
virtual ~Wrapper()
{
}
template <typename U>
WrapperT<U> * clone()
{
return new WrapperT<U>(value); //will not work, because value is not known here
}
};
template <typename T>
struct WrapperT : Wrapper
{
explicit WrapperT(T v)
{
value = v;
}
T value;
};
and I want something like this:
Wrapper *t = new WrapperT<int>(1);
WrapperT<double> *t2 = t->clone<double>();
I know virtual templates are not available. Any ideas?
A possible approach is defining a visitor pattern, but the cost of implementing the visitor might be large if you want to support many different wrapped types (i.e. if it is not just a small subset).
Another problem you would get is that the conversions would be (have to be) dynamically dispatched, so they can fail at runtime and you would have to provide mechanisms to detect that and act on that then (exceptions come to mind). Nothing horrible...
The solution I propose is using a "neutral type" to make dynamically (as David RodrÃguez - dribeas noted) the type conversion.
Advantage:
The solution is generic: you don't need to so any special thing when using a new type.
As drawbacks
Not good for performance.
Requires the insertion and extraction stream operators to be defined.
The code:
struct Wrapper
{
// get the "neutral type" value
virtual string getValue() const = 0;
template <typename U> Wrapper* clone() const;
};
template <typename T>
struct WrapperT: Wrapper
{
explicit WrapperT(T v): value(v)
{
}
virtual string getValue() const
{
// use streams to conversion to neutral value, but
// other better method would be suitable
ostringstream strm;
strm << value;
return strm.str();
}
T value;
};
template <typename U> Wrapper* Wrapper::clone() const {
U value;
istringstream strm(getValue());
strm >> value;
return new WrapperT<U>(value);
}
EDIT:
For a better performance solution, if only using numeric type, we can change string by a long double as "neutral type":
template <typename T>
double long WrapperT<T>::getValue() const
{
return value;
}
template <typename U> Wrapper* Wrapper::clone() const {
return new WrapperT<U>(getValue());
}
Do we want to avoid integral to floating point conversions when using only integral type? In that case, the solution will be a bit more complex:
create two getValue() virtual functions, one for integral and other one for floating point,
in clone() function select the desired getValue() function depending on U template parameter type (target type).
Related
I'm new to using templates and I want to make a function that returns generic types. I made a very simple template as such
enum tag { SHORT, INT, FLOAT, DOUBLE };
template <typename T>
T get_val(tag t){
switch (t) {
case SHORT: return .. //returns a short;
case INT: return .. //returns a int;
case FLOAT: return .. //returns a float;
case DOUBLE: return .. //returns a double;
}
}
the problem is that floats and doubles are returned as integer numbers. so I wonder why this happens and if there's a way I can use it properly.
You may not use a different return type using a switch statement like that.
However, if the input to get_val is known at compile time, you can use template metaprogramming techniques to get what you need.
enum tag { SHORT, INT, FLOAT, DOUBLE };
template <tag t> struct return_type_chooser;
template <> struct return_type_chooser<SHORT>
{
using type = short;
};
template <> struct return_type_chooser<INT>
{
using type = int;
};
template <> struct return_type_chooser<FLOAT>
{
using type = float;
};
template <> struct return_type_chooser<DOUBLE>
{
using type = double;
};
template <tag t>
typename return_type_chooser<T>::type get_val()
{
...
}
You can use:
get_val<SHORT>()
but not
get_val(SHORT)
Update, in response to OP's comment
If the input to get_val is known only at run time, std::any (C++17) or boost::any should work as the return type.
I would recommend doing this with a variant and runtime checks for the type among a limited subset of possible types:
Use a public interface taking a variant with an enum for the correct type (this is a naive version, you should really use std::variant and get_if):
enum variant_type
{
variant_null,
variant_int,
variant_float,
variant_double,
}
class variant
{
public:
// Add constructors with the correct type for the
// underlying storage
variant() = default;
variant(int x);
variant(float x);
variant(double x);
// ensure you can check for empty variants and check the type
explicit operator int() const;
explicit operator float() const;
explicit operator double() const;
explicit operator bool() const;
variant_type type() const;
private:
variant_type type_ = variant_null;
void* data_ = nullptr;
};
Then, add many custom function or method overloads that allow you to choose the correct method at runtime:
class my_handler
{
public:
my_handler(const variant& v)
{
switch (v.type()) {
case variant_null;
open(nullptr); break;
case variant_int;
open(int(v)); break;
case variant_float;
open(float(v)); break;
case variant_double;
open(double(v)); break;
}
}
private:
void open(std::nullptr_t nullp);
void open(int x);
void open(float x);
void open(double x);
};
This allows you to have a public interface that is generic for a limited subset of types, but that allows you to avoid having to know the correct type at compile-time.
This can all be done much more idiomatically using std::variant and get_if rather than writing your own custom variant class. I just this as an (inefficient) example of how many libraries (like the Windows API and Qt) have implemented their own.
I'm designing a library for internal use.
A function can be
template<typename It>
void doStuff(It begin, It end)
{
// This is example code. The point is to show that I access the data of the iterator
doStuffInternal(it->a, it->b, it->c);
}
This function is a template because I want to accept all kind of iterators, but I have specific expectations on the type that this iterators produce.
At the moment my code assumes an object is passed with a structure like
struct A
{
int a;
std::string b;
BigObject c;
};
I know the calling code of this function will receive data from an external API, and the data will look something like
struct AlmostA
{
int a_;
std::string _b;
AlmostBigObject cc;
};
Now I can't pass this AlmostA to my function and I need to convert it to A (or something that behaves like A), even if all the information are in AlmostA, just with different names (and slightly different types).
What I'm thinking about doing is to create a function to access the fields
inline int getA(const &A a)
{
return a.a;
}
inline std::string& getB(const &A a)
{
return a.b;
}
and so on for every field I need to access, then rewrite my function to be
template<typename It>
void doStuff(It begin, It end)
{
doStuffInternal(getA(*it), getB(*it), getC(*it));
}
Then the calling code can define
inline int getA(const &AlmostA a)
{
return a.a_;
}
inline std::string& getB(const &AlmostA a)
{
return a._b;
}
and call my function with an iterator of AlmostA without any conversion.
What I hope to achieve with this is that the calling code can define how they provide the information, without being forced to have a structure with those specific fields.
I googled around and couldn't find any example of code doing this.
I'm relatively new to C++, so I'd like if this would work, what are the pitfalls of this approach, why is it not popular or not used (I know something kind of similar is done with std::swap, but that's a particular function) what are alternative solutions to present data with different interface in a unified way in the C++ world?
In what namespace does the getter function need to be implemented in order for the compiler to find them?
Your doStuffInternal(getA(*it), getB(*it), getC(*it)) seems solid to me - I would use a struct template with an explicit specialization for every type that you need to support.
template <typename T>
struct adapter;
template <>
struct adapter<A>
{
template <typename T>
decltype(auto) a(T&& x) { return forward_like<T>(x.a); }
template <typename T>
decltype(auto) b(T&& x) { return forward_like<T>(x.b); }
// ...
};
template <>
struct adapter<AlmostA>
{
template <typename T>
decltype(auto) a(T&& x) { return forward_like<T>(x.a_); }
template <typename T>
decltype(auto) b(T&& x) { return forward_like<T>(x._b); }
// ...
};
Using decltype(auto) as the return type and forward_like allows you to preserve the value category of x's members:
static_assert(std::is_same<decltype(adapter<A>::a(A{})), int&&>{});
A lvalue{};
static_assert(std::is_same<decltype(adapter<A>::a(lvalue)), int&>{});
const A const_lvalue{};
static_assert(std::is_same<decltype(adapter<A>::a(const_lvalue)), const int&>{});
wandbox example (of the value category propagation)
The final code will look something like this:
template<typename It>
void doStuff(It begin, It end)
{
adapter<std::decay_t<decltype(*it)>> adp;
doStuffInternal(adp.a(*it), adp.b(*it), adp.c(*it));
}
In C++11, you need to explicitly specify the return type using a trailing return type. Example:
template <typename T>
auto a(T&& x) -> decltype(forward_like<T>(x.a_))
{
return forward_like<T>(x.a_);
}
I would like to define custom constants which can be used for an arbitrary type (e.g. float, double, etc.). As an example, suppose I wish to define a constant whose value is pi.
The obvious solution is to use #define pi 3.14159265359, but then pi would not be in a namespace and I risk a name collision. I'm not using C++14 so I can't use a variable template. The best way I can think to do this is like the following:
#include <iostream>
using namespace std;
namespace constants {
template<typename T> T pi() {
return 3.14159265359;
}
}
int main() {
float pitest = 0;
pitest = constants::pi<float>();
cout << pitest << endl;
cout << constants::pi<long double>() << endl;
cout << constants::pi<int>() << endl;
return 0;
}
I can now define these constants within a namespace and I can use an arbitrary (numerical) type as desired. However, there are at least two undesirable features of this:
It requires a function call which should not be necessary (it's just a constant!).
I have to specify the type in the function call, even if the function is returning to a variable of known type. For example, in the above code I have to use pitest = constants::pi<float>(); rather than simply pitest = constants::pi(); even though pitest is obviously a float.
Is there a better way to do this?
Why not use a special object with automatic conversion to any type?
static struct {
template<class T> operator T() const constexpr
{ return (T)3.14159265359; }
} pi;
You might even add specializations for bigger types, arbitrary-precision-arithmetic, formula-systems, whatever.
static struct { template<class T> operator T() const constexpr { return 3.14; } } pi;
is the first step.
template<class T> struct type {};
template<class T> constexpr T get_pi( type<T> ) { return 3.14; }
static struct { template<class T> operator T() const constexpr { return get_pi( type<T>{} ); } } pi;
is the second type -- now you can add new overloads for new types without having to specialize. All pi does is do the magic casting.
Sadly, this requires that we match the type exactly -- a new overload for int won't solve long, or a new overload for double won't solve float.
But this is C++, we can do it!
template<class T> struct contra_type {
constexpr contra_type(contra_type&&) {};
template<class U, class=typename std::enable_if< std::is_convertible< T, U >::value >::type>
constexpr contra_type( contra_type<U>&& ) {}
};
template<class T> constexpr auto get_pi( type<T>, ... )->decltype(T(3.14)) { return T(3.14); }
static struct { template<class T> operator T() const constexpr { return get_pi( contra_type<T>{} ); } } pi;
is the next step. Now we can add overloads for get_pi( type<bignum> ) and such and have it work. In fact, anything implicitly convertable from bignum will call get_pi( type<bignum> ) automatically.
Not sure how to enable ADL -- if I take a T*, I'll get covariant overloads not contravariant overloads (and as we are actually overloading on return type, that isn't want I want).
contra_type<U> is convertible to contra_type<T> if and only if T is convertable to U. This means that pi_func( contra_type<Foo>{} ) will attempt to find a pi_func that takes a type that can convert to Foo, and call that instead.
The ... overload gives us a default implementation that matches everything exactly, but because it has ... it will be preferred to call any other function instead of it that matches.
I want to implement a variant class that can store any datatype (like boost::any) but with the support of datatype conversion. For example,
Variant v1(int(23)); can be converted to bool via v1.get<bool>()
using Conv<int, bool>, Variant v2(CustomT1()); to CustomT2
via Conv<CustomT1, CustomT2> and so on.
Here is the current implementation, based on the idea of boost::any:
#include <iostream>
#include <string>
#include <memory>
#include <stdexcept>
template<typename Src, typename Dest>
struct Conv
{
/* static? */ Dest convert(const Src& src) const { throw std::runtime_error("type cast not supported"); }
};
template<> struct Conv<int, bool>
{
bool convert(const int &src) const { return src > 0; }
};
class IStoredVariant
{};
template<typename T>
struct variant_storage : public IStoredVariant
{
variant_storage(const T& value) : m_value(value)
{}
T& getValue(void) { return this->m_value; }
const T& getValue(void) const { return this->m_value; }
template<typename U>
U make_conversion(void) const // just an idea...
{
return Conv<U, T>().convert(this->getValue());
}
protected:
T m_value;
};
class Variant
{
public:
template<typename T>
Variant(const T& value) : m_storage(new variant_storage<T>(value))
{}
IStoredVariant& getImpl(void) { return *this->m_storage; }
const IStoredVariant& getImpl(void) const { return *this->m_storage; }
std::auto_ptr<IStoredVariant> m_storage;
template<typename T>
T get(void) const
{
const IStoredVariant &var = this->getImpl();
// ????????????
// How to perform conversion?
}
template<typename T>
void set(const T &value)
{
this->m_storage.reset(new variant_storage<T>(value));
}
};
int main(void)
{
Variant v(int(23));
bool i = v.get<bool>();
}
From the get<> template method, I only have access to an IStoredVariant pointer, but I need to know the concrete type to choose the Converter<>. Is there any design pattern or workaround to solve this problem?
This is impossible. You would need to have support for templates in virtual functions to make this happen.
In the calling context, you only have the type to be converted to, and you can't retrieve the stored type. In the called context, you only have the stored type and can't retrieve the type to be converted to.
There is no way to pass the type between them, so you can never know both types at once and therefore cannot perform any conversion.
Your problem is intractable.
If you have lost type information, then you cannot recover it (not fully) because the language itself does not support it (no reflexion/introspection).
You can still know the exact type, but you cannot get properties such as conversions to arbitrary types, because conversions mechanisms are baked in at compile-time (depending on constructors, conversion operators and language rules).
If you have only a small subset of types that you are interested in, then Boost.Variant is your best bet.
If you really wanted to have a fully dynamic language... then either ditch C++ or reimplement a dynamic language on top of C++...
You could use the typeid operator to get the type information of the type stored in the variant and compare this to the typeid of the T in get:
Extend the IStoredVariant with this interface definition:
class IStoredVariant
{
...
type_info getTypeId() = 0; // note the abstract definition
...
}
Add the implementation to the concrete variant storage:
template<typename T>
struct variant_storage : public IStoredVariant
{
...
type_info getTypeId() { return typeid(T); }
...
}
Use it in the Variant class:
class Variant
{
...
template<typename T>
T get(void) const
{
const IStoredVariant *var = this->getImpl();
if(typeid(T) == var->getTypeId())
{
// type matches: cast to the type
variant_storage<T>* my_typed_var = static_cast<variant_storage<T>* >(var);
// do something with it
}
}
}
EDIT: You can also look at the property implementation of OGRE which does not use typeid but enums for a specific set of types. All other types are therefore unsupported.
I just started playing with metaprogramming and I am working on different tasks just to explore the domain. One of these was to generate a unique integer and map it to type, like below:
int myInt = TypeInt<AClass>::value;
Where value should be a compile time constant, which in turn may be used further in meta programs.
I want to know if this is at all possible, and in that case how. Because although I have learned much about exploring this subject I still have failed to come up with an answer.
(P.S. A yes/no answer is much more gratifying than a c++ solution that doesn't use metaprogramming, as this is the domain that I am exploring)
In principle, this is possible, although the solution probably isn't what you're looking for.
In short, you need to provide an explicit mapping from the types to the integer values, with one entry for each possible type:
template< typename T >
struct type2int
{
// enum { result = 0 }; // do this if you want a fallback value
};
template<> struct type2int<AClass> { enum { result = 1 }; };
template<> struct type2int<BClass> { enum { result = 2 }; };
template<> struct type2int<CClass> { enum { result = 3 }; };
const int i = type2int<T>::result;
If you don't supply the fallback implementation in the base template, this will fail for unknown types if T, otherwise it would return the fallback value.
Depending on your context, there might be other possibilities, too. For example, you could define those numbers within within the types themselves:
class AClass {
public:
enum { inta_val = 1 };
// ...
};
class BClass {
public:
enum { inta_val = 2 };
// ...
};
// ...
template< typename T >
struct type2int
{
enum { result = T::int_val }; // will fail for types without int_val
};
If you give more context, there might be other solutions, too.
Edit:
Actually there isn't any more context to it. I was looking into if it actually was possible, but without assigning the numbers itself.
I think Mike's idea of ordering is a good way to do this (again, for a fixed set of types) without having to explicitly assign numbers: they're implicitly given by the ordering. However, I think that this would be easier by using a type list. The index of any type in the list would be its number. I think something like the following might do:
// basic type list manipulation stuff
template< typename T1, typename T2, typename T3...>
struct type_list;
// meta function, List is assumed to be some instance of type_list
template< typename T, class List >
struct index_of {
enum { result = /* find index of T in List */ };
};
// the list of types you support
typedef type_list<AClass, BClass, CClass> the_type_list;
// your meta function
template< typename T >
struct type2int
{
enum { result = index_of<T, the_type_list>::result };
};
This does what you want. Values are assigned on need. It takes advantage of the way statics in functions are assigned.
inline size_t next_value()
{
static size_t id = 0;
size_t result = id;
++id;
return result;
}
/** Returns a small value which identifies the type.
Multiple calls with the same type return the same value. */
template <typename T>
size_t get_unique_int()
{
static size_t id = next_value();
return id;
}
It's not template metaprogramming on steroids but I count that as a good thing (believe me!)
Similiar to Michael Anderson's approach but this implementation is fully standards compliant and can be performed at compile time. Beginning with C++17 it looks like constexpr values will be allowed to be used as a template parameter for other template meta programming purposes. Also unique_id_type can be compared with ==, !=, >, <, etc. for sorting purposes.
// the type used to uniquely identify a list of template types
typedef void (*unique_id_type)();
// each instantiation of this template has its own static dummy function. The
// address of this function is used to uniquely identify the list of types
template <typename... Arguments>
struct IdGen {
static constexpr inline unique_id_type get_unique_id()
{
return &IdGen::dummy;
}
private:
static void dummy(){};
};
The closest I've come so far is being able to keep a list of types while tracking the distance back to the base (giving a unique value). Note the "position" here will be unique to your type if you track things correctly (see the main for the example)
template <class Prev, class This>
class TypeList
{
public:
enum
{
position = (Prev::position) + 1,
};
};
template <>
class TypeList<void, void>
{
public:
enum
{
position = 0,
};
};
#include <iostream>
int main()
{
typedef TypeList< void, void> base; // base
typedef TypeList< base, double> t2; // position is unique id for double
typedef TypeList< t2, char > t3; // position is unique id for char
std::cout << "T1 Posn: " << base::position << std::endl;
std::cout << "T2 Posn: " << t2::position << std::endl;
std::cout << "T3 Posn: " << t3::position << std::endl;
}
This works, but naturally I'd like to not have to specify a "prev" type somehow. Preferably figuring out a way to track this automatically. Maybe I'll play with it some more to see if it's possible. Definitely an interesting/fun puzzle.
I think it is possible to do it for a fixed set of types, but quite a bit of work. You'll need to define a specialisation for each type, but it should be possible to use compile-time asserts to check for uniqueness. I'll assume a STATIC_ASSERT(const_expr), like the one in Boost.StaticAssert, that causes a compilation failure if the expression is false.
Suppose we have a set of types that we want unique IDs for - just 3 for this example:
class TypeA;
class TypeB;
typedef int TypeC;
We'll want a way to compare types:
template <typename T, typename U> struct SameType
{
const bool value = false;
};
template <typename T> struct SameType<T,T>
{
const bool value = true;
};
Now, we define an ordering of all the types we want to enumerate:
template <typename T> struct Ordering {};
template <> struct Ordering<void>
{
typedef TypeC prev;
typedef TypeA next;
};
template <> struct Ordering<TypeA>
{
typedef void prev;
typedef TypeB next;
};
template <> struct Ordering<TypeB>
{
typedef TypeA prev;
typedef TypeC next;
};
template <> struct Ordering<TypeC>
{
typedef TypeB prev;
typedef void next;
};
Now we can define the unique ID:
template <typename T> struct TypeInt
{
STATIC_ASSERT(SameType<Ordering<T>::prev::next, T>::value);
static int value = TypeInt<T>::prev::value + 1;
};
template <> struct TypeInt<void>
{
static int value = 0;
};
NOTE: I haven't tried compiling any of this. It may need typename adding in a few places, and it may not work at all.
You can't hope to map all possible types to an integer field, because there are an unbounded number of them: pointer types with arbitrary levels of indirection, array types of arbitrary size and rank, function types with arbitrary numbers of arguments, and so on.
I'm not aware of a way to map a compile-time constant integer to a type, but I can give you the next best thing. This example demonstrates a way to generate a unique identifier for a type which - while it is not an integral constant expression - will generally be evaluated at compile time. It's also potentially useful if you need a mapping between a type and a unique non-type template argument.
struct Dummy
{
};
template<typename>
struct TypeDummy
{
static const Dummy value;
};
template<typename T>
const Dummy TypeDummy<T>::value = Dummy();
typedef const Dummy* TypeId;
template<typename T, TypeId p = &TypeDummy<T>::value>
struct TypePtr
{
static const TypeId value;
};
template<typename T, TypeId p>
const TypeId TypePtr<T, p>::value = p;
struct A{};
struct B{};
const TypeId typeA = TypePtr<A>::value;
const TypeId typeB = TypePtr<B>::value;
I developed this as a workaround for performance issues with ordering types using typeid(A) == typeid(B), which a certain compiler fails to evaluate at compile time. It's also useful to be able to store TypeId values for comparison at runtime: e.g. someType == TypePtr<A>::value
This may be doing some "bad things" and probably violates the standard in some subtle ways... but thought I'd share anyway .. maybe some one else can sanitise it into something 100% legal? But it seems to work on my compiler.
The logic is this .. construct a static member function for each type you're interested in and take its address. Then convert that address to an int. The bits that are a bit suspect are : 1) the function ptr to int conversion. and 2) I'm not sure the standard guarantees that the addresses of the static member functions will all correctly merge for uses in different compilation units.
typedef void(*fnptr)(void);
union converter
{
fnptr f;
int i;
};
template<typename T>
struct TypeInt
{
static void dummy() {}
static int value() { converter c; c.f = dummy; return c.i; }
};
int main()
{
std::cout<< TypeInt<int>::value() << std::endl;
std::cout<< TypeInt<unsigned int>::value() << std::endl;
std::cout<< TypeInt< TypeVoidP<int> >::value() << std::endl;
}
I don't think it's possible without assigning the numbers yourself or having a single file know about all the types. And even then you will run into trouble with template classes. Do you have to assign the number for each possible instantiation of the class?
type2int as compile time constant is impossible even in C++11. Maybe some rich guy should promise a reward for the anwser? Until then I'm using the following solution, which is basically equal to Matthew Herrmann's:
class type2intbase {
template <typename T>
friend struct type2int;
static const int next() {
static int id = 0; return id++;
}
};
template <typename T>
struct type2int {
static const int value() {
static const int id = type2intbase::next(); return id;
}
};
Note also
template <typename T>
struct type2ptr {
static const void* const value() {
return typeid(T).name();
}
};