Basicly, I need a static_cast function wrapper to use as a predicate (for conversion), since static_cast directly is not usable in this way. Lambda is not preferred this time. My implemention:
template<typename T>
struct static_cast_forward{
template<class U>
T operator()(U&& u) const {
return static_cast<T>(std::forward<U>(u));
}
};
First, while I do have a fundamental understanding of rvalue references, etc. I want to verify if this is the correct way to implement this forward/wrapper ?
Second, to ask if any std or boost library already provide this functionality ?
Extra: would you forward other casts in the same way ?
ACTUAL CASE:
My actual case is to use with boost::range, something like:
//auto targetsRange = mixedRange | boost::adaptors::filtered(TYPECHECK_PRED) | boost::adaptors::transformed(static_cast_forward<TARGET_PTR_TYPE>());
WORKING EXAMPLES:
#include <algorithm>
template<typename T>
struct static_cast_forward {
template<class U>
T operator()(U&& u) const {
return static_cast<T>(std::forward<U>(u));
}
};
//example 1:
void test1() {
std::vector<double> doubleVec{1.1, 1.2};
std::vector<int> intVec;
std::copy(doubleVec.begin(), doubleVec.end(), intVec.end());//not ok (compiles, but gives warning)
std::transform(doubleVec.begin(), doubleVec.end(), std::back_inserter(intVec), static_cast_forward<int>()); //ok
}
//example 2:
struct A {
virtual ~A() {}
};
struct B : public A {
};
struct C : public A {
};
void test2() {
std::vector<A*> vecOfA{ new B, new B};
std::vector<B*> vecOfB;
//std::transform(vecOfA.begin(), vecOfA.end(), std::back_inserter(vecOfB), static_cast<B*>); //not ok: syntax error..
std::transform(vecOfA.begin(), vecOfA.end(), std::back_inserter(vecOfB), static_cast_forward<B*>() ); //ok
}
Addition after the question has been clarified.
In both cases you don't need to std::forward anything, because there is nothing to move, you need just a cast. But if you want to generalize to movable types, too, then your implementation seems fine to me. Just don't call it forward because it is not a forward. As far as I know, there is nothing in std to mimic your struct.
So I would just add test3() that really needs moving:
struct B { };
struct D {
explicit D(B&&) { } // Note: explicit!
};
void test3()
{
std::vector<B> vb{B{}, B{}};
std::vector<D> vd;
// Won't compile because constructor is explicit
//std::copy(std::make_move_iterator(vb.begin()), std::make_move_iterator(vb.end()), std::back_inserter(vd));
// Works fine
std::transform(std::make_move_iterator(vb.begin()), std::make_move_iterator(vb.end()), std::back_inserter(vd), static_cast_forward<D>());
}
Answer before question was clarified.
If I correctly understood your intention, then this is what you want:
template<typename T>
struct static_cast_forward {
template<class U>
decltype(auto) operator()(U&& u) const
{
if constexpr (std::is_lvalue_reference_v<U>)
return static_cast<T&>(u);
else
return static_cast<T&&>(u);
}
};
Then you have:
struct B { };
struct D : B { };
void foo() {
D d;
static_cast_forward<B> scf_as_B;
static_assert(std::is_same_v<decltype(scf_as_B(D{})), B&&>);
static_assert(std::is_same_v<decltype(scf_as_B(d)), B&>);
}
Related
I have
class ClassA {};
class ClassB {};
auto func_a() -> ClassA {
return ClassA(); // example implementation for illustration. in reality can be different. does not match the form of func_b
}
auto func_b() -> ClassB {
return ClassB(); // example implementation for illustration. in reality can be different. does not match the form of func_a
}
I want to be able to use the syntax
func<ClassA>() // instead of func_a()
func<ClassB>() // instead of func_b()
(this is as part of a bigger template)
but I don't know how to implement this template specialization for the function alias.
Help? What is the syntax for this?
[Edit] The answers posted so far do not answer my question, so I'll edit my question to be more clear.
The actual definition of func_a and func_b is more complex than just "return Type();". Also they cannot be touched. So consider them to be
auto func_a() -> ClassA {
// unknown implementation. returns ClassA somehow
}
auto func_b() -> ClassB {
// unknown implementation. returns ClassB somehow
}
I cannot template the contents of func_a or func_b. I need the template for func<ClassA|ClassB> to be specialized for each one of the two and be able to select the correct one to call
You might do something like (c++17):
template <typename T>
auto func()
{
if constexpr (std::is_same_v<T, ClassA>) {
return func_a();
} else {
return func_b();
}
}
Alternative for pre-C++17 is tag dispatching (which allows customization point):
// Utility class to allow to "pass" Type.
template <typename T> struct Tag{};
// Possibly in namespace details
auto func(Tag<ClassA>) { return func_a(); }
auto func(Tag<ClassB>) { return func_b(); }
template <typename T>
auto func() { return func(Tag<T>{}); }
You can do it like this :
#include <iostream>
#include <type_traits>
class A
{
public:
void hi()
{
std::cout << "hi\n";
}
};
class B
{
public:
void boo()
{
std::cout << "boo\n";
}
};
template<typename type_t>
auto create()
{
// optional : if you only want to be able to create instances of A or B
// static_assert(std::is_same_v<A, type_t> || std::is_same_v<B, type_t>);
type_t object{};
return object;
}
int main()
{
auto a = create<A>();
auto b = create<B>();
a.hi();
b.boo();
return 0;
}
Suppose I have this class :
class Component1;
class Component2;
// many different Components
class Component42;
class MyClass
{
public:
MyClass(void) {};
std::list<Component1> component1List;
std::list<Component2> component2List;
// one list by component
std::list<Component42> component42List;
};
I would like to create a function with the following signature:
template<class T> void addElement(T component);
It should do the following:
if component is of type Component1, add it to Component1List
if component is of type Component2, add it to Component2List, etc.
Is it possible? What's a good way to do this?
I can obtain the same behaviour with a function like :
template<class T> void addElement(int componentType, T component);
but I'd rather not have to specify the componentType like this : it's useless information and it open the door to possible errors (if componentType doesn't represent the type of component).
std::tuple to the rescue.
changelog:
use std::decay_t
added the variadic argument form
add_component() now returns a reference to this to allow call-chaining.
#include <iostream>
#include <list>
#include <utility>
#include <type_traits>
#include <tuple>
class Component1 {};
class Component2 {};
struct Component3 {
Component3() {}
};
// many different Components
template<class...ComponentTypes>
class MyClassImpl
{
template<class Component> using list_of = std::list<Component>;
public:
using all_lists_type =
std::tuple<
list_of<ComponentTypes> ...
>;
// add a single component
template<class Component>
MyClassImpl& add_component(Component&& c)
{
list_for<Component>().push_back(std::forward<Component>(c));
return *this;
}
// add any number of components
template<class...Components>
MyClassImpl& add_components(Components&&... c)
{
using expand = int[];
void(expand { 0, (void(add_component(std::forward<Components>(c))), 0)... });
return *this;
}
template<class Component>
auto& list_for()
{
using component_type = std::decay_t<Component>;
return std::get<list_of<component_type>>(_lists);
}
template<class Component>
const auto& list_for() const
{
using component_type = std::decay_t<Component>;
return std::get<list_of<component_type>>(_lists);
}
private:
all_lists_type _lists;
};
using MyClass = MyClassImpl<Component1, Component2, Component3>;
int main()
{
MyClass c;
c.add_component(Component1());
c.add_component(Component2());
const Component3 c3;
c.add_component(c3);
c.add_components(Component1(),
Component2(),
Component3()).add_components(Component3()).add_components(Component1(),
Component2());
std::cout << c.list_for<Component1>().size() << std::endl;
return 0;
}
The most straightforward variant is to simply not use templates but to overload the addElement() function:
void addElement(Component1 element)
{
this->element1List.push_back(element);
}
void addElement(Component2 element)
{
this->element2List.push_back(element);
}
// ... etc
However, this might get tedious if you have many of these (and you don't just have addElement(), I guess). Using a macro to generate the code for each type could still do the job with reasonable effort.
If you really want to use templates, you could use a template function and specialize the template function for each type. Still, this doesn't reduce the amount of code repetition when compared with the above approach. Also, you could still reduce it using macros to generate the code.
However, there's hope for doing this in a generic way. Firstly, let's create a type that holds the list:
template<typename T>
struct ComponentContainer
{
list<T> componentList;
};
Now, the derived class just inherits from this class and uses C++ type system to locate the correct container baseclass:
class MyClass:
ComponentContainer<Component1>,
ComponentContainer<Component2>,
ComponentContainer<Component3>
{
public:
template<typename T>
void addElement(T value)
{
ComponentContainer<T>& container = *this;
container.componentList.push_back(value);
}
}
Notes here:
This uses private inheritance, which is very similar to the containment you originally used.
Even though ComponentContainer is a baseclass, it doesn't have any virtual functions and not even a virtual destructor. Yes, this is dangerous and should be documented clearly. I wouldn't add a virtual destructor though, because of the overhead it has and because it shouldn't be needed.
You could drop the intermediate container altogether and derive from list<T>, too. I didn't because it will make all of list's memberfunctions available in class MyClass (even if not publicly), which might be confusing.
You can't put the addElement() function into the base class template to avoid the template in the derived class. The simple reason is that the different baseclasses are scanned in order for a addElement() function and only then overload resolution is performed. The compiler will only find the addElement() in the first baseclass therefore.
This is a plain C++98 solution, for C++11 I'd look at the type-based tuple lookup solutions suggested by Jens and Richard.
If there are not too many classes you could go with overloading. A template-based solution could be done with type-based lookup for tuples:
class MyClass {
public:
template<typename T> void addElement(T&& x) {
auto& l = std::get<std::list<T>>(lists);
l.insert( std::forward<T>(x) );
}
private:
std::tuple< std::list<Component1>, std::list<Component2> > lists;
};
If you don't know in advance the types you will need storing when instantiating the multi-container an option is to hide the types and using type_index to keep a map of lists:
struct Container {
struct Entry {
void *list;
std::function<void *(void*)> copier;
std::function<void(void *)> deleter;
};
std::map<std::type_index, Entry> entries;
template<typename T>
std::list<T>& list() {
Entry& e = entries[std::type_index(typeid(T))];
if (!e.list) {
e.list = new std::list<T>;
e.deleter = [](void *list){ delete ((std::list<T> *)list); };
e.copier = [](void *list){ return new std::list<T>(*((std::list<T> *)list)); };
}
return *((std::list<T> *)e.list);
}
~Container() {
for (auto& i : entries) i.second.deleter(i.second.list);
}
Container(const Container& other) {
// Not exception safe... se note
for (auto& i : other.entries) {
entries[i.first] = { i.second.copier(i.second.list),
i.second.copier,
i.second.deleter };
}
};
void swap(Container& other) { std::swap(entries, other.entries); }
Container& operator=(const Container& other) {
Container(other).swap(*this);
return *this;
};
Container() { }
};
that can be used as:
Container c;
c.list<int>().push_back(10);
c.list<int>().push_back(20);
c.list<double>().push_back(3.14);
NOTE: the copy constructor as written now is not exception safe because in case a copier throws (because of an out of memory or because a copy constructor of an element inside a list throws) the already allocated lists will not be deallocated.
void addElement(Component1 component) {
componentList1.insert(component);
}
void addElement(Component2 component) {
componentList2.insert(component);
}
I'd like to fill in the store() and launch() methods in the below code. The important detail which captures the spirit of the problem is that the object foo declared in main() no longer exists at the time we call launch(). How can I do this?
#include <cstdio>
#include <cstring>
#include <type_traits>
template<typename T, typename U=
typename std::enable_if<std::is_trivially_copyable<T>::value,T>::type>
struct Launchable {
void launch() { /* some code here */ }
T t;
// other members as needed to support DelayedLauncher
};
class DelayedLauncher {
public:
template<typename T>
void store(const Launchable<T>& t) {
// copy-construct/memcpy t into some storage
}
void launch() const {
// call t.launch(), where t is (a copy of) the last value passed into store()
}
// other members as needed
};
int main() {
DelayedLauncher launcher;
{
Launchable<int> foo;
launcher.store(foo);
}
launcher.launch(); // calls foo.launch()
return 0;
}
Note that if we only had a fixed set of N types to pass into store(), we could achieve the desired functionality by declaring N Launchable<T> fields and N non-template store() methods, one for each type, along with an enum field whose value is use in a switch statement in the launch() method. But I'm looking for an implementation of DelayedLauncher that will not need modification as more Launchable types are added.
using std::function:
class DelayedLauncher {
public:
template<typename T>
void store(const Launchable<T>& t) {
f = [t]() {t.launch();};
}
void launch() const { f(); }
private:
std::function<void()> f;
};
You could give Launchable a base class with a virtual launch() and no template, and store pointers to that base class in Launcher::store.
EDIT: Adapted from #dshin's solution:
struct LaunchableBase {
virtual void launch() = 0;
};
template<typename T, typename U=
typename std::enable_if<std::is_trivially_copyable<T>::value,T>::type>
struct Launchable : public LaunchableBase {
virtual void launch() override { /* some code here */ }
T t;
// other members as needed to support DelayedLauncher
};
class DelayedLauncher {
public:
template<typename T>
void store(const Launchable<T>& t) {
static_assert(sizeof(t) <= sizeof(obj_buffer),
"insufficient obj_buffer size");
static_assert(std::is_trivially_destructible<T>::value,
"leak would occur with current impl");
p = new (obj_buffer) Launchable<T>(t);
}
void launch() const {
p->launch();
}
private:
char obj_buffer[1024]; // static_assert inside store() protects us from overflow
LaunchableBase *p;
};
I believe this variant of Jarod42's solution will avoid dynamic allocation, although I would appreciate if someone could confirm that this will work the way I think it will:
class DelayedLauncher {
public:
template<typename T>
void store(const Launchable<T>& t) {
static_assert(sizeof(t) <= sizeof(obj_buffer),
"insufficient obj_buffer size");
static_assert(std::is_trivially_destructible<T>::value,
"leak would occur with current impl");
auto p = new (obj_buffer) Launchable<T>(t);
auto ref = std::ref(*p);
f = [=]() {ref.get().launch();};
}
void launch() const {
f();
}
private:
char obj_buffer[1024]; // static_assert inside store() protects us from overflow
std::function<void()> f;
};
I believe it should work because the resources I've looked at indicate that std::function implementations typically have a "small capture" optimization, only triggering a dynamic allocation if the total size of the captured data exceeds some threshold.
EDIT: I replaced my code with a version provided by Jarod42 in the comments. The standard guarantees the above implementation will not trigger dynamic allocation.
I want to write a function that return different types based on different input as below.
enum MyType
{
A,
B
};
template<MyType T> struct MyStruct
{
};
static auto createMyStruct(MyType t)
{
if(t==A)
return MyStruct<A>();
else
return MyStruct<B>();
}
It didn't work out because there are two return types for one auto. Is there any other way to do this?
There is absolutely no way of having a (single) function that returns different types based on a runtime decision. The return type has to be known at compile time. However, you can use a template function, like this (thanks to #dyp for making me simplify the code):
#include <iostream>
#include <typeinfo>
enum MyType
{
A,
B
};
template<MyType>
struct MyStruct {};
template<MyType type>
MyStruct<type> createMyStruct()
{
return {};
}
int main()
{
auto structA = createMyStruct<A>();
auto structB = createMyStruct<B>();
std::cout << typeid(structA).name() << std::endl;
std::cout << typeid(structB).name() << std::endl;
}
I am assuming you want to write code like this:
void foo (MyType t) {
auto x = createMyStruct(t);
//... do something with x
}
You are attempting to derive the right type for x at runtime. However, the return type of a function must be known at compile time, and the type resolution for auto is also determined at compile time.
You could instead restructure your code to be like this:
template<MyType T> struct MyStruct
{
//...
static void foo () {
MyStruct x;
//... do something with x
}
};
The idea is to write a single foo() function whose only difference is the type of thing it is manipulating. This function is encapsulated within the type itself. You can now make a runtime decision if you have a mapping between MyType and MyStruct<MyType>::foo.
typedef std::map<MyType, void(*)()> MyMap;
template <MyType...> struct PopulateMyMap;
template <MyType T> struct PopulateMyMap<T> {
void operator () (MyMap &m) {
m[T] = MyStruct<T>::foo;
}
};
template <MyType T, MyType... Rest> struct PopulateMyMap<T, Rest...> {
void operator () (MyMap &m) {
m[T] = MyStruct<T>::foo;
PopulateMyMap<Rest...>()(m);
}
};
template<MyType... Types> void populateMyMap (MyMap &m) {
PopulateMyMap<Types...>()(m);
}
//...
populateMyMap<A, B>(myMapInstance);
Then, to make a runtime decision:
void foo (MyType t) {
myMapInstance.at(t)();
}
I think you should learn abstract factory design pattern.
For use objects of type MyStruct<A> or MyStruct<B> you need common interface.
Common interface provided in abstract base class.
struct MyStruct
{
virtual ~MyStruct() {}
virtual void StructMethod() = 0;
};
struct MyStructA: public MyStruct
{
void StructMethod() override {}
};
struct MyStructB: public MyStruct
{
void StructMethod() override {}
};
std::unique_ptr<MyStruct> createMyStruct(MyType t)
{
if (t==A)
return std::make_unique<MyStructA>();
else
return std::make_unique<MyStructB>();
}
This is easier to explain with some code so I'll give an example first:
#include <iostream>
#include <vector>
class Base {
public:
int integer;
Base() : integer(0) {}
Base(int i) : integer(i) {}
};
class Double: public Base {
public:
Double(int i) { integer = i * 2; }
};
class Triple: public Base {
public:
Triple(int i) { integer = i * 3; }
};
template<typename T>
Base* createBaseObject(int i) {
return new T(i);
};
int main() {
std::vector<Base*> objects;
objects.push_back(createBaseObject<Double>(2));
objects.push_back(createBaseObject<Triple>(2));
for(int i = 0; i < objects.size(); ++i) {
std::cout << objects[i]->integer << std::endl;
}
std::cin.get();
return 0;
}
I am trying to make a function that will return a Base pointer to an object that is derived from Base. In the above code the function createBaseObject allows me to do that but it restricts me in that it can only create dervied classes that take a single argument into their constructor.
For example if I wanted to make a derived class Multiply:
class Multiply: public Base {
public:
Multiply(int i, int amount) { integer = i * amount; }
};
createBaseObject wouldn't be able to create a Multiply object as it's constructor takes two arguments.
I want to ultimately do something like this:
struct BaseCreator {
typedef Base* (*funcPtr)(int);
BaseCreator(std::string name, funcPtr f) : identifier(name), func(f) {}
std::string identifier;
funcPtr func;
};
then, for example, when I get input matching identifier I can create a new object of whatever derived class associates with that identifier with whatever arguments were input too and push it to the container.
After reading some of the replies I think something like this would suit my needs to be able to procedurally create an instance of an object? I'm not too wise with templates though so I do not know whether this is legal.
struct CreatorBase {
std::string identifier;
CreatorBase(std::string name) : identifier(name) {}
template<typename... Args>
virtual Base* createObject(Args... as) = 0;
};
template<typename T>
struct Creator: public CreatorBase {
typedef T type;
template<typename... Args>
Base* createObject(Args... as) {
return new type(as...);
}
};
Okay here's another semi-solution I've managed to come up with so far:
#include <boost\lambda\bind.hpp>
#include <boost\lambda\construct.hpp>
#include <boost\function.hpp>
using namespace boost::lambda;
boost::function<Base(int)> dbl = bind(constructor<Double>(), _1);
boost::function<Base(int, int)> mult = bind(constructor<Multiply>(), _1, _2);
Just this has the same limits as the original in that I can't have a single pointer that will point to both dbl and mult.
C++11 variadic templates can do this for you.
You already have your new derived class:
class Multiply: public Base {
public:
Multiply(int i, int amount) { integer = i * amount; }
};
Then change your factory:
template<typename T, typename... Args>
Base* createBaseObject(Args... as) {
return new T(as...);
};
And, finally, allow the arguments to be deduced:
objects.push_back(createBaseObject<Multiply>(3,4));
Live demo.
As others have said, though, it does all seem a little pointless. Presumably your true use case is less contrived.
Why not provide multiple overloads with templated parameters?
template<typename TBase, TArg>
Base* createBaseObject(TArg p1) {
return new TBase(p1);
};
template<typename TBase, TArg1, TArg2>
Base* createBaseObject(TArg p1, TArg2 p2) {
return new TBase(p1, p2);
};
Use variadic templates:
template <typename R, typename ...Args>
Base * createInstance(Args &&... args)
{
return new R(std::forward<Args>(args)...);
}
Usage: objects.push_back(createInstance<Gizmo>(1, true, 'a'));
It's a bit hard to see why you would want this, though, as you might as well just say:
objects.push_back(new Gizmo(1, true, 'a'));
Even better would be to declare the vector to carry std::unique_ptr<Base> elements.