I have question about having a std::function object as a data member for my class. I would like for it to accept two types of functions, either with one or two parameters of the same kind. Is there some strategy for doing this, perhaps involving template meta programming?
Here's a copy of my code so far, and to be clear I would like it to only accept std::function<matrix (matrix, matrix)> and std::function<matrix (matrix)> .
struct RegisteredOPS {
using matrix = std::shared_ptr<Matrix::Representation>;
enum Type { NOP, MM, PLUS, ReLU,};
Type m_type;
std::function<matrix (matrix, matrix)> m_func;
RegisteredOPS(Type _typ, std::function<matrix
(matrix, matrix)> _fun): m_type(_typ), m_func(_fun) {}
};
As a followup, I went and followed the suggestion of
#Lala5th, my question is if there is any way to wrap a functor object in std::function<matrix (matrix, matrix)> ?
I have the following Base class Functor adhering to CRTP:
template <class Implementation>
class BaseOp {
public:
virtual std::unique_ptr<Matrix::Representation> operator()(
std::unique_ptr<Matrix::Representation>& l,
std::unique_ptr<Matrix::Representation>& r) {
return Impl().operator()(l, r);
}
virtual ~BaseOp() = default;
private:
BaseOp& Impl() { return *static_cast<Implementation*>(this); }
BaseOp() = default;
friend Implementation;
};
where I am attempting to pass it via this function:
void RegisterOperator::visit(std::unique_ptr<MatrixMultiplyStep> mm) {
std::string context_object_data = "Matrix_multiply";
auto operand = mm->giveOperand();
RegisteredOperation op = RegisteredOperation(
RegisteredOperation::MM,
&Matrix::Operations::
Multiplication::ParallelDNC::operator(),
std::make_pair(std::move(this->prev_operand), std::move(operand)));
this->computational_graph.emplace_back(op);
// mm->forward(std::make_unique<this>());
}
However I ended up with this error.
tensor.cpp:20:42: error: no matching constructor for initialization of 'NeuralNetwork::Computation::Graph::RegisteredOperation'
RegisteredOperation op = RegisteredOperation(
^
include/tensor.h:59:21: note: candidate constructor not viable: no known conversion from 'std::unique_ptr<Matrix::Representation> (Matrix::Operations::Multiplication::ParallelDNC::*)(std::unique_ptr<Matrix::Representation> &, std::unique_ptr<Matrix::Representation> &)' to 'NeuralNetwork::Computation::Graph::RegisteredOperation::Function' (aka 'variant<function<unique_ptr<Matrix::Representation> (unique_ptr<Matrix::Representation>, unique_ptr<Matrix::Representation>)>, function<unique_ptr<Matrix::Representation> (unique_ptr<Matrix::Representation>)>, function<void ()>>') for 3rd argument
RegisteredOperation(Type _typ, std::string _dat, Function _fun, Operands _op):
Thank you!
Related
I understand that for a class
class A {
const int myint;
public:
A (const int yourint);
A (const std::string yourstring);
};
I could initialize myint in the initializer list like so:
A::A (const int yourint) : myint (yourint) {};
However, what is the proper way of initializing myint from the second constructor if the the data required to compute it comes say from a string and the computations may be involved?
Use a function call inside a delegating (if avaliable, not neccessarily) constructor's member initialization list:
A::A(std::string const& yourstring) : A(compute_myint(yourstring)) {};
Pass std::string by const&, not just const, while you're at it.
compute_myint can be non-member, static member, possibly not accessible from outside the class, whichever makes the most sense.
Here you would want to use delegating constructors, if you can, or you could compute in the ctor. See my second example for the second option. An example for your class would be:
Option 1: Delegating Constructors: C++11 forward
class A {
const int myint;
static int parse_int(const std::string& string) {/*...*/}
public:
A (const int yourint) : myint{yourint};
A (const std::string yourstring) : A{parse_int(yourstring)};
}
By the way, since parse_int only computes integers, then it could be static, meaning it does not require a class instance to be used. Of course, there is no requirement, as the function could be a member just as well, (non static), although static is safer, since it will almost always guarantee the construction of the object.
Option 2: Constructor Computation, non delegating
This method could be used in any C++ version.
class A {
const int myint;
static int parse_int(const std::string& string) {/*...*/}
public:
A (const int yourint) : myint(yourint);
A (const std::string yourstring) : my_int(parse_int(yourstring));
}
Just use a member function.
Keep in mind that it's safer (i.e. less error-prone) to use a static member function for things like this than a non-static one, because the class isn't fully initialized yet when the function is called.
class A {
const int myint;
public:
A(const int x) : myint(x) {}
A(std::string const& s) : myint(compute(s)) {}
private:
static int compute(std::string const& s) { return (int)s.length(); }
};
I've been annoyed by this issue quite a few times, so I have developed a small utility to solve it in the general case. The full code is as follows:
namespace initBlock_detail {
struct tag { };
template <class F>
decltype(auto) operator + (tag, F &&f) {
return std::forward<F>(f)();
}
}
#define initBlock \
initBlock_detail::tag{} + [&]() -> decltype(auto)
And it is used as follows:
int const i = initBlock {
// Any complex calculation
// and then return the value
return foo;
};
See it live on Coliru
The structure is similar to Andrei Alexandrescu's ScopeGuard implementation, which uses an infix operator overload and a lambda to achieve that light syntax. i's type can be deduced, can be a reference, etc. Other useful features include the possibility to place using namespace declarations inside the init-block. Any movable and/or copyable type can be used.
I'm not sure how best to phrase the question, but I'm not asking how to implement templated virtual functions per-se. I'm building an entity component system, and I have two important classes - World and Entity. World is actually an abstract class, and the implementation (let's call it WorldImpl) is a templated class that allows use of a custom allocator (one that can be used with std::allocator_traits).
Components are any data type which we can attach to entities. This is done by calling a templated function named assign on the entity.
Here's the problem: I'm trying to make the entity use the world's allocator when creating and initializing components. In a perfect world, you would call Entity::assign<ComponentType>( ... ) which would ask the WorldImpl to create the component with whatever allocator is appropriate. There's a problem here, however - The entity has a pointer to World and templated virtual functions aren't possible to my knowledge.
Here's a bit more of an illustration that might make the issue more obvious:
class Entity
{
template<typename ComponentType>
void assign(/* ... */)
{
/* ... */
ComponentType* component = world->createComponent<ComponentType>(/* ... */);
/* ... */
}
World* world;
};
// This is the world interface.
class World
{
// This is the ideal, which isn't possible as it would require templated virtual functions.
template<typename ComponentType>
virtual ComponentType* createComponent(/* ... */) = 0;
};
template<typename Allocator>
class WorldImpl : public World
{
template<typename ComponentType> // again, not actually possible
virtual ComponentType* createComponent(/* ... */)
{
// do something with Allocator and ComponentType here
}
};
Seeing as the above code isn't actually possible, here's the real question: With a class hierarchy such as this, what black magic do I have to do in order for some function to be called with both the ComponentType and Allocator template parameters? This is the ultimate goal - a function called on some object with both template parameters available to it.
I'd say that Entities belong to a certain kind of world and make them templates with a World parameter. Then you can forget about all the inheritance and virtual and just implement worlds that fulfill the required interface, e.g.
template<typename World>
class Entity
{
template<typename ComponentType>
void assign(/* ... */)
{
/* ... */
ComponentType* component = world.createComponent<ComponentType>(/* ... */);
/* ... */
}
World world;
};
template<typename Allocator>
class WorldI
{
template<typename ComponentType>
ComponentType* createComponent(/* ... */)
{
// do something with Allocator and ComponentType here
}
};
Note that this isn't an optimal solution (see the bottom of the post for issues), but a somewhat-viable way to combine templates and virtual functions. I post it in the hopes that you can use it as a basis to come up with something more efficient. If you can't find a way to improve on this, I would suggest templating Entity, as the other answer suggested.
If you don't want to do any major modifications to Entity, you can implement a hidden virtual helper function in World, to actually create the component. In this case, the helper function can take a parameter which indicates what kind of component to construct, and return void*; createComponent() calls the hidden function, specifying ComponentType, and casts the return value to ComponentType*. The easiest way I can think of is to give each component a static member function, create(), and map type indexes to create() calls.
To allow each component to take different parameters, we can use a helper type, let's call it Arguments. This type provides a simple interface while wrapping the actual parameter list, allowing us to easily define our create() functions.
// Argument helper type. Converts arguments into a single, non-template type for passing.
class Arguments {
public:
struct ArgTupleBase
{
};
template<typename... Ts>
struct ArgTuple : public ArgTupleBase {
std::tuple<Ts...> args;
ArgTuple(Ts... ts) : args(std::make_tuple(ts...))
{
}
// -----
const std::tuple<Ts...>& get() const
{
return args;
}
};
// -----
template<typename... Ts>
Arguments(Ts... ts) : args(new ArgTuple<Ts...>(ts...)), valid(sizeof...(ts) != 0)
{
}
// -----
// Indicates whether it holds any valid arguments.
explicit operator bool() const
{
return valid;
}
// -----
const std::unique_ptr<ArgTupleBase>& get() const
{
return args;
}
private:
std::unique_ptr<ArgTupleBase> args;
bool valid;
};
Next, we define our components to have a create() function, which takes a const Arguments& and grabs arguments out of it, by calling get(), dereferencing the pointer, casting the pointed-to ArgTuple<Ts...> to match the component's constructor parameter list, and finally obtaining the actual argument tuple with get().
Note that this will fail if the Arguments was constructed with an improper argument list (one that doesn't match the component's constructor's parameter list), just as calling the constructor directly with an improper argument list would; it will accept an empty argument list, however, due to Arguments::operator bool(), allowing default parameters to be provided. [Unfortunately, at the moment, this code has issues with type conversion, specifically when the types aren't the same size. I'm not yet sure how to fix this.]
// Two example components.
class One {
int i;
bool b;
public:
One(int i, bool b) : i(i), b(b) {}
static void* create(const Arguments& arg_holder)
{
// Insert parameter types here.
auto& args
= static_cast<Arguments::ArgTuple<int, bool>&>(*(arg_holder.get())).get();
if (arg_holder)
{
return new One(std::get<0>(args), std::get<1>(args));
}
else
{
// Insert default parameters (if any) here.
return new One(0, false);
}
}
// Testing function.
friend std::ostream& operator<<(std::ostream& os, const One& one)
{
return os << "One, with "
<< one.i
<< " and "
<< std::boolalpha << one.b << std::noboolalpha
<< ".\n";
}
};
std::ostream& operator<<(std::ostream& os, const One& one);
class Two {
char c;
double d;
public:
Two(char c, double d) : c(c), d(d) {}
static void* create(const Arguments& arg_holder)
{
// Insert parameter types here.
auto& args
= static_cast<Arguments::ArgTuple<char, double>&>(*(arg_holder.get())).get();
if (arg_holder)
{
return new Two(std::get<0>(args), std::get<1>(args));
}
else
{
// Insert default parameters (if any) here.
return new Two('\0', 0.0);
}
}
// Testing function.
friend std::ostream& operator<<(std::ostream& os, const Two& two)
{
return os << "Two, with "
<< (two.c == '\0' ? "null" : std::string{ 1, two.c })
<< " and "
<< two.d
<< ".\n";
}
};
std::ostream& operator<<(std::ostream& os, const Two& two);
Then, with all that in place, we can finally implement Entity, World, and WorldImpl.
// This is the world interface.
class World
{
// Actual worker.
virtual void* create_impl(const std::type_index& ctype, const Arguments& arg_holder) = 0;
// Type-to-create() map.
static std::unordered_map<std::type_index, std::function<void*(const Arguments&)>> creators;
public:
// Templated front-end.
template<typename ComponentType>
ComponentType* createComponent(const Arguments& arg_holder)
{
return static_cast<ComponentType*>(create_impl(typeid(ComponentType), arg_holder));
}
// Populate type-to-create() map.
static void populate_creators() {
creators[typeid(One)] = &One::create;
creators[typeid(Two)] = &Two::create;
}
};
std::unordered_map<std::type_index, std::function<void*(const Arguments&)>> World::creators;
// Just putting in a dummy parameter for now, since this simple example doesn't actually use it.
template<typename Allocator = std::allocator<World>>
class WorldImpl : public World
{
void* create_impl(const std::type_index& ctype, const Arguments& arg_holder) override
{
return creators[ctype](arg_holder);
}
};
class Entity
{
World* world;
public:
template<typename ComponentType, typename... Args>
void assign(Args... args)
{
ComponentType* component = world->createComponent<ComponentType>(Arguments(args...));
std::cout << *component;
delete component;
}
Entity() : world(new WorldImpl<>())
{
}
~Entity()
{
if (world) { delete world; }
}
};
int main() {
World::populate_creators();
Entity e;
e.assign<One>();
e.assign<Two>();
e.assign<One>(118, true);
e.assign<Two>('?', 8.69);
e.assign<One>('0', 8); // Fails; calls something like One(1075929415, true).
e.assign<One>((int)'0', 8); // Succeeds.
}
See it in action here.
That said, this has a few issues:
Relies on typeid for create_impl(), losing the benefits of compile-time type deduction. This results in slower execution than if it was templated.
Compounding the issue, type_info has no constexpr constructor, not even for when the typeid parameter is a LiteralType.
I'm not sure how to obtain the actual ArgTuple<Ts...> type from Argument, rather than just casting-and-praying. Any methods of doing so would likely depend on RTTI, and I can't think of a way to use it to map type_indexes or anything similar to different template specialisations.
Due to this, arguments must be implicitly converted or casted at the assign() call site, instead of letting the type system do it automatically. This... is a bit of an issue.
VisualStudio 2008 (VC++ 9)
Problem with overloading operator()
Hello community!
It seems that overloaded version of operator() must all differ in their argument list, independly of the return type.
I have the following case:
class Sha256{
public:
QVector<quint32> operator()(QString const& data);
QByteArray operator()(QByteArray const& data);
QVector<quint32> operator()(QByteArray const& data); // this is line 168
...
}
Last declaration leads to following compilation error:
.\sha256.cpp(168) : error C2556: 'QVector Sha256::operator ()(const QByteArray &)' : overloaded function differs only by return type from 'QByteArray Sha256::operator ()(const QByteArray &)'
with
[
T=uint
]
On the other side, following declarations are working:
class Sha256{
public:
QVector<quint32> operator()(QString const& data);
QByteArray operator()(QByteArray const& data);
...
}
because they have different arguments.
One way would be to add in the first case an additional argument like
QByteArray<quint32> operator()(QByteArray const& data, bool getByteArray)
but this is embarassing, not intuitive and also not clean (return type would be a QByteArray, independly of the value of getByteArray, even in case of false!).
Another way could be to use a template function like
template<class T> T operator()(QByteArray const& ba)
template<class T> T operator()(QString const& str)
but T could only be of a few 'supported' type (QByteArray and QVector), therefore user could run into trouble if using wrong T Type. This version seems to be error prone.
So my questions are:
1. Why is the return type of function objects not taken into account in the signature to distinguish between different flavors of the function like in 'classical' functions?
2. Is there a better way around than adding an additional dummy argument?
Thank you for your valuable time.
Alain
Return type is never used for overload resolution. In fact, you can't even declare two functions that differ only in return type. In my opinion, adding this feature would be complicated and not that helpful. Is it necessary to use the function call operator? You could just use a named member function, and then give them different names. Another option would be to use a member template, but even then you would need to explicitly give the return type as a template argument, and the syntax would be ugly if done on the function call operator.
The comment from Kerrek SB suggests a workaround by leveraging conversion operators, if you are okay with something that is complex on the inside, but simpler on the outside.
#include <iostream>
struct A {};
struct B {};
A fooA_impl(const char *) {
std::cerr << "A impl" << std::endl;
return A();
}
B fooB_impl(const char *) {
std::cerr << "B impl" << std::endl;
return B();
}
class Helper {
public:
operator A() { return fooA_impl(p); }
operator B() { return fooB_impl(p); }
private:
friend Helper foo(const char *p);
Helper(const char *p_) : p(p_) {}
const char *const p;
};
Helper foo(const char *p) {
return Helper(p);
}
int
main() {
A a(foo("hello"));
B b(foo("hello"));
}
You can't use overload by return type. One thing you can do is to add the return type as a tag parameter when overloading operator():
QByteArray operator()(QByteArray const& data, const QByteArray& tag );
QVector<quint32> operator()(QByteArray const& data, const QVector<quint32>& tag);
The below is how you call these function:(assume both types have default constructors).
(data, QByteArray());
(data, QVector<quint32>());
Observe the following program in which a function accepts both the expected type and any type that is a typedef of that type.
//a user defined type
class Widget{};
//a function that takes a Widget
void function (Widget w){}
int main(){
//make a typedef (this is C++11 syntax for a typedef. It's the same thing)
using Gadget = Widget;
//make the two "different types" (well.. they're not really different as you will see)
Widget w;
Gadget g;
//call a function that should ONLY accept Widgets
function(w); //works (good)
function(g); //<- works (I do not want this to compile though)
}
As you can see, a typedef does not actually distinguish a new type. I thought instead to inherit from the type:
//inherit instead
class Gadget: public Widget{};
//make the two "different types"
Widget w;
Gadget g;
//call the function that should ONLY accept widgets
function(w); //works (good)
function(g); //<- works (I do not want this to compile though)
Same problem.
Looking at boost, I thought to try a strong typedef:
#include <boost/serialization/strong_typedef.hpp>
//a user defined type
class Widget{};
//a function that takes the user defined type
void function (Widget w){}
int main(){
//try to strongly typedef
BOOST_STRONG_TYPEDEF(Widget, Gadget)
//make the two "different types"
Widget w;
Gadget g;
//call the function that should ONLY accept widgets
function(w);
function(g);
}
compile errors:
In member function ‘bool main()::Gadget::operator==(const main()::Gadget&) const’:
error: no match for ‘operator==’ (operand types are ‘const Widget’ and ‘const Widget’)
BOOST_STRONG_TYPEDEF(Widget, Gadget)
^
In member function ‘bool main()::Gadget::operator<(const main()::Gadget&) const’:
error: no match for ‘operator<’ (operand types are ‘const Widget’ and ‘const Widget’)
BOOST_STRONG_TYPEDEF(Widget, Gadget)
^
Apparently BOOST_STRONG_TYPEDEF only works on primitive types.
I tried to do inheritance again, but stop the implicit conversion:
//I want the functionality, but these are NOT the same type!
class Gadget: public Widget{
operator Widget() = delete;
};
That did not work either.
Questions:
Why does boost strong_typedef only work on primitive types?
How can I 'typedef' a non-primitive type to get functionality similar to boost strong_typef?
Basically you need two unrelated classes with the same behavior. I would use a parametrized template for that:
template<int tag> class WidgetGadget { ... };
typedef WidgetGadget<0> Widget;
typedef WidgetGadget<1> Gadget;
BOOST_STRONG_TYPEDEF actually assumes that types are equatable (==), assignable (=) and less-than-comparable (<).
If your type isn't, then the macro results in code that doesn't compile, as you have witnessed. You can roll your own macro or provide implementations for the required operations.
You can find a CUSTOM_STRONG_TYPEDEF in this answer from februari 2012: How to use comparison operators on variant with contained types?, which explicitly avoids getting the default comparison behaviour
Update Made the example more explicit for your use case, see it Live On Coliru
//a user defined type
class Widget{};
class Frobnicator{};
/////////////////////////////////////////////////////
// copied and reduced from boost/strong_typedef.hpp
#define CUSTOM_STRONG_TYPEDEF(T, D) \
struct D \
/*: boost::totally_ordered1< D */ \
/*, boost::totally_ordered2< D, T */ \
/*> > */ \
{ \
T t; \
explicit D(const T t_) : t(t_) {}; \
D(){}; \
D(const D & t_) : t(t_.t){} \
D & operator=(const D & rhs) { t = rhs.t; return *this;} \
D & operator=(const T & rhs) { t = rhs; return *this;} \
explicit operator const T & () const {return t; } \
explicit operator T & () { return t; } \
/*bool operator==(const D & rhs) const { return t == rhs.t; } */\
/*bool operator<(const D & rhs) const { return t < rhs.t; } */\
};
CUSTOM_STRONG_TYPEDEF(Widget, Gadget)
CUSTOM_STRONG_TYPEDEF(Frobnicator, Normalcy)
void acceptWidget(Widget){}
void acceptGadget(Gadget){}
void acceptFrobnicator(Frobnicator){}
void acceptNormalcy(Normalcy){}
int main(){
//make the two "different types" (well.. they're not really different as you will see)
Widget w;
Gadget g;
//call a function that should ONLY accept Widgets
acceptWidget(w); //works (good)
acceptGadget(g);
//acceptWidget(g); // Error
//acceptGadget(w); // Error
// but we can enjoy conversions if we summon them
acceptWidget(static_cast<Widget&>(g));
Frobnicator f;
Normalcy n;
acceptFrobnicator(f);
acceptNormalcy(n);
}
Maybe you could use private inheritance and some usings?
class Gadget : Widget { using Widget::Widget; using Widget::foo; ... };
I am not a template or type casting expert, so I really need some help.
I have to use an existing template class and encounter the following type cast problem.
I put some sample code to illustrtrate the problem.
//template class definition
template <class IntType>
class CUSTOMIZE_Int: public CUSTOMIZE_Type
{
public:
operator const IntType() const;
private:
IntType m_int;
}
template<class IntType>
CUSTOMIZE_Int<IntType>::operator const IntType() const
{
return m_int;
}
// the template class instantiation
typedef CUSTOMIZE_Int<WRAPPER_Int32> CUSTOMIZE_UnsignedInt;
Then in my code, I derive a new class
// the derived class definition
class IntNum: public CUSTOMIZE_UnsignedInt
{
// ctors and new methods;
}
and creat a variable, and try to make the conversion to get the data.
class IntNum& i;
const WRAPPER_Int32 j = i;
with the following compile error:
error: cannot convert "IntNum" to "const WRAPPER_Int32" in initialization.
What is the right way to do the conversion, or what is the problem with my code?
Thanks for any comments!
I guess that you expect operator IntType()
class ...
operator const IntType() const;
}
to act here, when you assign i to j:
const WRAPPER_Int32 j = i;
However, this is not an implicit conversion, you must do it explicitely:
const WRAPPER_Int32 j = (WRAPPER_Int32) i;
Hope this helps.