How to implement template class with template-dependent signal member from boost? - c++

I try to implement a template class which requires to have a signal member that depends on the template argument. My first idea was to realize it like the following:
template<class T>
class SignalClass
{
typedef boost::signals2::signal<void (T &)> OnReceive;
public:
SignalClass(const OnReceive::slot_type &_slot)
{
m_onReceive.cnnect(_slot);
}
virtual SignalClass(){};
void Send(T &_val)
{
m_onReceive(_val);
}
private:
OnReceive m_onReceive;
};
An that class should be used like:
class SignaledClass
{
public:
SignaledClass(void)
{
SignalClass<int> var1(boost::bind(&SignaledClass::ReceiveINT, this));
SignalClass<double> var2(boost::bind(&SignaledClass::ReceiveDOUBLE, this));
}
void ReceiveINT(int &_val)
{
...
}
void ReceiveDOUBLE(double &_val)
{
...
}
}
(BTW: I know, that it makes no sense to create the SignalClass object just inside the constructor. It's just to understand my problem.)
It is important for me to realize a delegate-like concept with a template as signal parameter.
The problem is that the constructor code doesn't work.
But I found a solution.
If I additionally specify an additional typedef like
typedef typename OnReceive::slot_type slot_type;
and use that a parameter for the constructor, like
PushInputSlot(const slot_type& _slot);
the it works.
But I have no real clue why.
I hope that somebody can help me.
Thanx,
Frank
P.S.: I'm new on stackoverflow thats why I'm not familiar with the rules here. Hope I've done everything in the right way... ;-)....

Here is the reason why adding typename (either directly in the constructor argument or in an additional typedef) works:
First, the type OnReceive is a so-called "dependent type", because it depend on the type of the template parameter.
Then, templates are processed in two stages in the compiler: The first stage is when the compiler encounters the source text for the template and the second stage is when the template is actually instantiated.
During the first stage of processing, the compiler will (should) try to validate as far as possible that the template definition is correct, but it runs into a problem when it comes to dependent types. Because a dependent type depends on the template parameters, the compiler does not know what the actual type will look like.
In particular, when accessing a member with the :: operator, the compiler needs some help deciding if the member is expected to refer to a member-type (typedef or nested class) or a non-type member (a variable, enum, etc.). This can be resolved by adding typename before the (full) type-name if you know that it should refer to a type.
The other place where the compiler might have a problem is differentiating between a member-template and a non-template member involved in a less-than comparison. This is resolved by adding the keyword template before the name of the member-template (immediately after the operator).

Related

Using Concepts to create static polymorphic interface

Hello Stackoverflow community,
I've been really confused on the concepts syntax and am having a hard time getting started.
I would like to create a polymorphic interface for two types of operator types: unary and binary and opted to try out the concept feature in c++20.
Not sure if it matters, but I used a CRTP create my unary functor compatible with binary functors, however I would like to get rid of that. Here's what I have so far:
template <typename T>
concept UnaryMatrixOperatable = requires(T _op) {
_op.template operate(std::unique_ptr<Matrix::Representation>{});
{_op.template operate() } -> same_as<std::unique_ptr<Matrix::Representation>>;
};
class ReLU : public UnaryAdapter<ReLU> {
public:
std::unique_ptr<Matrix::Representation> operate(
const std::unique_ptr<Matrix::Representation>& m);
};
static_assert(UnaryMatrixOperatable<ReLU>);
However, I am getting a compilation error, presumably because I am not doing some sort of template specialization for a const matrix & type?
include/m_algorithms.h:122:13: error: static_assert failed
static_assert(UnaryMatrixOperatable<ReLU>);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/m_algorithms.h:122:27: note: because 'Matrix::Operations::Unary::ReLU' does not satisfy 'UnaryMatrixOperatable'
static_assert(UnaryMatrixOperatable<ReLU>);
^
include/m_algorithms.h:53:26: note: because '_op.template operate(std::unique_ptr<Matrix::Representation>{})' would be invalid: 'operate' following the 'template' keyword does not refer to a template
_op.template operate(std::unique_ptr<Matrix::Representation>{});
^
Thanks for all the help in advance, this design in my code has been problematic for over a week so I'm determined to find a clean way to fix it! Thanks.
Concepts are not base classes, and you should not treat concept requirements like base class interfaces. Base classes specify exact function signatures that derived classes must implement.
Concepts specify behavior that must be provided. So you explain what that behavior is.
The behavior you seem to want is that you can pass an rvalue of a unique pointer to an operate member function. So... say that.
template <typename T>
concept UnaryMatrixOperatable = requires(T _op, std::unique_ptr<Matrix::Representation> mtx)
{
_op.operate(std::move(mtx));
};
There's no need for template here because you do not care if operate is a template function. It's not important in the slightest to your code if any particular T happens to implement operate as a template function or not. You're going to call it this way, so the user must specify some function interface that can be called a such.
The same goes for the zero-argument version. Though your interface should probably make it much more clear that you're moving from the unique pointer in question:
template <typename T>
concept UnaryMatrixOperatable = requires(T _op, std::unique_ptr<Matrix::Representation> mtx)
{
_op.operate(std::move(mtx));
{ std::move(_op).operate() } -> std::same_as<decltype(mtx)>;
};
In any case, the other reason you'll get a compile error is that your interface requires two functions: one that gets called with an object and one that does not. Your ReLu class only provides one function that pretends to do both.

Type erasure and variadic templated member function

The example below is a minimal, maybe not so good example of a well known idiom.
It compiles and it is so ugly in order to be able to maintain it minimal, because the question is not about the idiom itself.
struct Foo {
virtual void fn() = 0;
};
template<class T>
struct Bar: public Foo {
void fn() override {
T{}.fn();
}
};
struct S {
void fn() { }
};
int main() {
Foo *foo = new Bar<S>{};
foo->fn();
}
What I'm struggling with since an hour ago is how to change it (or even, if there exists an alternative idiom) to introduce a variadic template member method.
Obviously, I cannot modify the fn function of the Foo class, because it's a virtual one and virtual specifier doesn't goes along with templates. The same is valid for the fn specification of Bar, because it has to override somehow the one in the base class.
Note.
For I strongly suspect that this question could be one of the greatest XYProblem ever seen, I'd like also to give a brief description of the actual problem.
I have a class that exposes two templated member methods:
the first one accepts a template class T that is not used immediately, instead it should be stored somehow in order to be used later.
the second one accepts a variadic number of arguments (it is actually a variadic templated member function) and those arguments should be perfectly forwarded to a newly created instance of T.
Well, the problem is far more complex, but this is a good approximation of it and should give you an idea of what's the goal.
Edit
I guess that it is somehow similar to higher order functions.
I mean, what would solve the problem is indeed a templated function to which to bind the first argument, but as far as I know this is impossible as well as any other approach I've explored so far.
Any viable solution that expresses the same concept?
What I mentioned in the comments is the following approach:
template<typename T> class Factory {
public:
template<typename ...Args>
auto construct(Args && ...args)
{
return T(std::forward<Args>(args)...);
}
};
So now, your first exposed class method will be something like this:
template<typename T>
auto getFactory() {
return Factory<T>();
}
So:
auto factory=object.getFactory<someClass>();
// Then later:
factory.construct(std::string("Foo"), bar()); // And so on...
Instead of construct() you could use operator() too, so the second part of this becomes, simply:
factory(std::string("Foo"), bar()); // And so on...
As I mentioned, this is not really type erasure. You can't use type erasure here.
Having given this a few minutes' more thought, the reason that type erasure cannot be used here is because a given instance of type erasure must be "self contained", or atomic, and what you need to do is to break atomic type erasure into two parts, or two class methods, in your case.
That won't work. Type erasure, by definition, takes a type and "erases" it. Once your first function type-erases its class method template parameter, what you end up with is an opaque, type-erased object of some kind. What was type-erased is no longer available, to the outside world. But you still haven't type-erased your constructor parameters, which occurs somewhere else.
You can type-erase the template class, and the constructor parameters together. You can't type-erase the template class, and the constructor parameters, separately and then somehow type-erase the result again.
The simple factory-based approach, like the one I've outlined, would be the closest you can get to results that are similar to type erasure, if both halfs of your desired type-erasure appear in the same scope, so you can actually avoid type-erasure, and instead rely on compiler-generated bloat.
I also agree that you cannot do exactly what you want here. I will post what I think the closest option is (at least a close option that is different from SamVarshavchik's answer).
I don't expect this answer to solve your problem exactly, but hopefully it will give you some ideas.
struct Delay // I have no idea what to call this
{
template <class T>
void SetT()
{
function_ = [](boost::any params){return T(params);}
}
template <class ... Args>
boost::any GetT(Args ... args)
{
return function_(std::make_tuple(args...));
}
private:
std::function<boost::any(boost::any)> function_;
};
The obvious limitation of this is that anyone calling GetT will somehow have to know what T was already, though you can query the boost::any object for the type_info of its class if that helps. The other limitation here is that you have to pass in T's that take a boost::any object and know what to do with it. If you cannot have T do that, then you can change SetT (or create a new member function) like this:
template <class F>
SetTFactory(F f)
{
function_ = f;
}
and then use it like:
Delay d;
d.SetTFactory([](boost::any s){return std::string(boost::any_cast<const char*>(s));});
auto s = d.GetT("Message");
assert(s.type() == typeid(std::string));
This of course introduces a whole new set of difficulties to deal with, so I don't know how viable this solution will be for you. I think regardless of anything else, you're going to have to rethink your design quite a bit.

multiple functions with same name but different argument types as template parameter

I'm using xsd to create c++ code from a xml schema file. For a xml type multiple functions are created (for serialization etc).
If the type is called XmlType multiple functions of the following form are created:
XmlType XmlType_(const XmlType& a, const string& b)
string XmlType_(const XmlType& a)
...
This are normal functions and not members of XmlType and they all have the same name.
For XmlType2 the functions would be called XmlType2_.
I would like to write a utility template class for all the different xml types of my xml scheme. The different functions are going to be called insight this class. What I have so far is something like this:
template<typename T>
using TFunc1 = T (*)(const T&, const string&);
template<typename T>
using TFunc2 = string (*)(const T&);
template<typename T, TFunc1<T> func2, TFunc2<T> func2>
class XmlUtil {
...
};
When create an instance of the XmlUtil class if have to do it like this:
XmlUtil<XmlType, XmlType_, XmlType_> util;
This feels a bit redundant and gets worse, when I have to pass more functions as parameters.
I would like to use the util class like this:
XmlUtil<XmlType, XmlType_> util;
or even better like this
XmlUtil<XmlType> util;
The only way I can think of is to somehow use define, but it doesn't feel right.
Is there an other way to do this?
EDIT:
I'm using a define now:
#define TRPL(name) name, name ## _, name ## _
...
XmlUtil<TRPL(XmlType)> util;
I'll edit this, if I find something better (maybe override sets like Yakk suggested in his answer).
This:
XmlUtil<XmlType> util;
is impossible because there is no way to get from XmlType to XmlType_. Their relationship is discarded after the automatic code generator.
However this:
XmlUtil<XmlType_> util;
may be possible. You can deduce the function type of XmlType_ and then use the deduced return type which will be XmlType. I believe there are standard library function for this purpose.
As for the two different overloads, that may be trickier. I do not think that you can pass a function overload set as a template parameter, the resolution is done on the template argument in the context of the template parameter to one function. I don't think there is a way to defer this action without using the preprocessor.
So I would argue that you should use a #define. It is better than nothing.
This looks like a job for override sets.
static struct foo_override_set_type {
template<typename... Args>
auto operator()( Args...&& args ) const
->
decltype( foo( std::forward<Args>(args)... ) )
{ return ( foo( std::forward<Args>(args)... ) ); }
template<typename T>
operator T() { return foo; }
} foo_override_set;
Objects of type foo_override_set_type represent the entire override set of foo. Calling them with operator() does an override set lookup on foo and calls the resulting function. Casting them to a function pointer does the same thing as casting the token foo to a function pointer (or other value).
Your code generation can auto-generate such override set types. It can also make a traits class that maps from your type XmlType to the override set of XmlType_ functions via specialization.
Then, your XmlUtil<XmlType> can access the override set of XmlType_ via that traits class. It first instantiates the override set variable, then invokes () on it.
As an aside, #Xeo has a proposal to make creating such objects as easy as typing []XmlType_ in C++1y or C++1z.
Default template arguments in the class definition?
Like
template<typename T, TFunc1<T> func1 = XmlType_, TFunc2<T> func2 = XmlType_>
class XmlUtil {
// ...
};
You can use a trait class like this
template <typename T>
struct Trait{
typedef T type;
typedef T (*func1)(const T&, const string&);
typedef string (*func2)(const T&);
};
and make the class XmlUtil have one template parameter (let's name it Trait) and use Trait::type, Trait::func1 and Trait::func2. See here for full usage.
In the example, the type of XmlUtil goes like:
XmlUtil<Trait<XmlType> >
I've done it this way since I don't know well your problem. It might be the case that you can just define the Trait class right into XmlUtil and use
XmlUtil<XmlType>
Other variations are possible, it just depend on what you need.
You can read a very brief introduction to trait classes here. If you want to read more about this topic I suggest you Modern C++ (Alexandrescu).
I am not sure I fully understand what you are asking. The common approach for serialization and deserialization would be to create a factory (abstract factory) and resolve the construction of the objects dynamically. Note that this can be improved for complex structures, where the code generator can create member functions to extract the exact type of each one of the members.
But again, I don't fully understand what you are really trying to do... As a recommendation I believe it would help if you provided more of a description of the problem to solve, as the question focuses on how to make your solution work, and that implicitly discards other approaches that might be better designs.

Any way to determine if class implements operator()

I'm trying to find is there's a way to check if a class is a functional because i want to write a template which uses it?
Is there an easy way to do this? Or do I just wrap things in a try/catch? Or perhaps the compiler won't even let me do it?
If you have a function template written like:
template <typename T>
void f(T x)
{
x();
}
you will be unable to instantiate it with any type that is not callable as a function taking no arguments (e.g., a class type that overloads operator() taking no arguments is callable as a function that takes no arguments). You would get a compilation error if you tried to do so.
This is the simplest way to require the type with which a template is instantiated to have certain properties: just rely on the type having those properties when you write the template, and if the type doesn't have one of the required properties, it will be impossible to instantiate the template with that type.
There are quite a few ways a parameter type can be applicable to the call syntax
Type is a pointer or reference to a function type, or
Type is a class-type which has a conversion function to one of the types in 1., or has an applicable operator().
The current C++ cannot check for 2., so you are left without checking, like the other answers explain.
This would fall under doing it and getting a compiling error. When the code is compiled the template function or template classes are are expanded for the types used as if there were duplicate copies of that template code, one for each type.
So you can basically do whatever and as long as all the types used for your templates support it you have no problem. If they don't support it you have a compiling error and you can't run your code without fixing it.
template <typename T>
void DoIt(T a)
{
a.helloworld();//This will compile fine
return a();//This will cause a compiling error if T is B
}
class A
{
public:
void a.helloworld(){}
void operator()(){}
};
class B
{
public:
void a.helloworld(){}
};
int main(int argc, char**argv)
{
A a;
B b;
DoIt(a);
DoIt(b);//Compiling error
return 0;
}
If you actually need a test to see if type T implements an operator() of some given signature then you could use the same SFINAE trick used to identify the existence of any other class member that is discussed here: C++ "if then else" template substitution

c++ template casting

I'm a little lost in how to cast templates. I have a function foo which takes a parameter of type ParamVector<double>*. I would like to pass in a ParamVector<float>*, and I can't figure out how to overload the casting operator for my ParamVector class, and Google isn't helping me that much. Does anyone have an example of how to do this? Thanks.
EDIT: Adding some code, sorry I'm an idiot and didn't phrase the original question well at all;
template<class T> class ParamVector
{
public:
vector <T> gnome;
vector <T> data_params;
}
template<class T> class ParamVectorConsumer
{
public:
ParamVector<T> test;
}
ParamVector<float> tester;
ParamVectorConsumer<double> cons;
cons.ParamVector = tester
will fail to compile. I would like to know how to write it so that I can cast the float version of tester to a ParamVector double. Thanks
EDIT2: Casting was the wrong word. I don't mind writing extra code, I just need to know how to get this to be accepted by the compiler so that I can write some sort of conversion code.
I'm not sure but maybe you need some like this:
template< typename TypeT >
struct ParamVector
{
template < typename NewTypeT >
operator ParamVector< NewTypeT >()
{
ParamVector< NewTypeT > result;
// do some converion things
return result;
}
template< typename NewTypeT >
ParamVector( const ParamVector< NewTypeT > &rhs )
{
// convert
}
template < typename NewTypeT >
ParamVector& operator=( const ParamVector< NewTypeT > &rhs )
{
// do some conversion thigns
return *this;
}
};
ParamVector< double > d1;
ParamVector< float > f1;
f1 = d1;
You can choose use conversion operator or operator= - I've provided both in my example.
Well, you can't. Each different actual template parameter, makes an entirely new class, which has no* relation inheritance relation with any any other class, with a diffent actual argument, made from that template.
No relationship. Well, except that each provides the same interface, so that inside a template you can handle then the same.
But neither the static types or the dynamic types have any relation.
Let me drop back here, and explain.
When I declare a pointer to classtype, like
Foo fp*;
fp has what we call a static type, of pointer-to Foo. If class Bar is a subclass of Foo, and I point fp at new Bar:
fp = new Bar1();
then we say that the object pointed to by fp has the dynamic type of Bar.
if Bar2 also publicly derives from Foo, I can do this:
fp = new Bar2();
and without ever even knowing what fp points to, I can call virtual methods declared in Foo, and have the compiler make sure that the method defined in he dynamic type pointed to is what's called.
For a template< typename T > struct Baz { void doSomething(); };
Baz<int> and Baz<float> are two entirely different class types, with no relationship.
The only "relationship" is that I can call doSomething() on both, but since the static types have no relationship, if I have a Baz<int> bi*, I can't point it to a Baz<float>. Not even with a cast. The compiler has no way to "translate" a call to the Baz doSotheing method into a call to a Baz::doSomething() method. That's because there is no "Baz method", there is no Baz, there are ony Baz<int>s and Baz<float>s, and Baz<whatevers>, but there's no common parent. Baz is not a class, Baz is a template, a set of instructions about how to make a class if and only if we have a T parameter that's bound to an actual type (or to a constant).
Now there is one way I can treat those Bazes alike: in a template, they present the same interface, and the compiler, if it knows what kind of Baz we're really dealing with, can make a static call to that method (or a static access of a member variable).
But a template is not code, a template is meta-code, the instructions of how to synthesize a class. A "call" in a template is not a call,it's an instruction of how to write the code to make a call.
So. That was long winded and confusing. Outside of a template definition, there is no relationship between a ParamVector and aParamVector. So your assignment can't work.
Well. Almost.
Actually, with partial application of templates, you can write a template function which gives a "recipe" of how to transform a Paramvector<T> to a ParamVector<U>. Notice the T and the U. If you can write code to turn any kind of ParamVector, regardless of actual template parameter into any other kind of ParamVector, you can package that up as a partially applied template, and the compiler will add that function to, for example, ParamVector.
That probably involves making a ParamVector<U>, and transforming each T in the ParamVector<T> into a U to put in the ParamVector<U>. Which still won't let you asign to a ParamConsumer<T>.
So maybe you want to have both templates and inheritance. In that case, you can same that all ParamVectors regardless of type inherit from some non-template class. And then there would be a relationship between ParamVectors, they'd all be sibling subclasses of that base class.
Notice that when you do an implicit cast, what the compiler can do without your help (I mean, without additional code) is just reference-upcast. That means that, seeing the object as a reference (for cast purposes only, the nature of the object doesn't change of course), it can look at it as one of its ancestors. When you have two template instances, none of them is an ancestor of the other (neither they are necessarily in the same hierarchy).
After trying that, the compiler looks for cast operators, constructors, etc. At this stage, probably a temporary object needs to be created, except when you're doing attribution and there's an attribution operator that fits.
One solution to your problem would be to use a conversion constructor:
template<class T> class ParamVector
{
public:
vector <T> gnome;
vector <T> data_params;
ParamVector()
{
}
template <class T2> ParamVector(const ParamVector<T2> &source)
{
gnome.reserve(source.gnome.size());
copy(source.gnome.begin(), source.gnome.end(), gnome.begin());
data_params.reserve(source.data_params.size());
copy(source.data_params.begin(), source.data_params.end(), data_params.begin());
}
};
This would create a temporary object whenever you use an instance of the template and other is required. Not a good solution if you're dealing with large containers, the overhead isn't acceptable. Also, if you pass a template instance to a function that requires not an object but a reference, the compiler won't call the conversion constructor automatically (you have to do an explicit call).
You are lost because you can't do it - the two types are completely different. Whenever you come across the need for a cast in your code, you should examine both your code and your design very closely - one or both is probably wrong.
You can't do this with a direct cast because double and float are completly different sizes. Doubles are going to be 64 bits while floats are 32. A pointer forced to cast from a
ParamVector<float>
to
ParamVector<double>
is going to misinterpret the data and give you garbage. You may want to google "pointer aliasing" or just learn more about pointers in general to see how this isn't going to work.
Think about it for a second you have one array that is a bunch of 64 bit values with fields layed out like this
0 => abcdabcd12341234
1 => abcdabcd12341234
If you force this to be interpreted as an array of 32 bit values, its going to not be interpreted correctly. You may or may not get something like
0 => abcdabcd
1 => 12341234
2 => abcdabcd
3 => abcdabcd
or it could be switched so that the 12341234's come first, or something stranger due to how the word ordering works out.
You mentioned "template casting" in your headline, so I'll presume that ParamVector is a templated type. That means that foo could be templated as well, and that would solve your problem.
template <typename T>
void foo(ParamVector<T> const& data)
{
}
You can't cast templates like this because the types are unrelated.
However, you can add a conversion function, such as:
(Your code wasn't really complete, so I can post complete code either. Hopefully you will get the idea.)
template<class T> class ParamVectorConsumer
{
public:
ParamVector<T> test;
template<T2> ParamVectorConsumer<T2> convert()
{
ParamVectorConsumer<T2> ret;
ret = this->...
}