If I do something like
mixin template T() {
float y;
this(float y_){
y = y_;
}
}
class C {
mixin T!() t;
int x;
this(int x_, float y_){
x = x_;
this(y_);
}
}
//
C c = new C(5, 7.0f);
This gives the error
constructor C.this (int x_, float y_) is not callable using argument types (float). On the line that contains this(y_); in C's constructor, which seems to imply that C can't see the constructor imported from T. Though, it should.
Obviously t.this(...) and T!().this(...) don't work.
The most obvious workaround I can think of is like (a proxy):
template T(...) {
void constructor(...){...}
this(Args...)(Args args){ constructor(args); }
}
...
class C {
mixin T!() t;
this(...){
t.constructor(...);
}
}
But that sucks because it puts more knowledge overhead on T (using the constructor requires doing something special)
Is there any way to call t's constructor in a non-weird (and non-special-case) way? Also, is this a bug? If not, why does it work this way?
The issue stems from the fact that things mixed into an aggregate via mixin templates are not inserted into the aggregate's overload set.
For normal methods the way to get around that is to use an alias into the scope introduced by the template mixin like so:
mixin template T()
{
void foo()
{
}
}
class C
{
mixin T!() t;
alias foo = t.foo;
void foo(int _)
{
foo();
}
}
However, for constructors, the analogue doesn't work and it's a reported bug:
alias this = t.this; // Won't compile
alias __ctor = t.__ctor // Using the hidden __ctor name won't compile, either
If you don't need to call the mixed in constructor from outside, you can call it via the builtin name:
mixin template T()
{
float y;
this(float y_)
{
y = y_;
}
}
class C
{
mixin T!() t;
int x;
this(int x_, float y_)
{
x = x_;
t.__ctor(y_); // This
}
}
Related
I have a class that has a constructor taking quite a few parameters
enum class FooType {FOO_A, FOO_B, FOO_C};
class Foo {
Foo(const double a, const double b, .... const double n);
}
depending on the 'type', I only need a certain subset of the params. At the moment there are various constructors with different number of inputs, but some new types will be added so that the number of inputs is the same. I could just add the type to the constructor, have a long switch in it, but the params list is quite long.
Foo(FooType type, const double a, const double b, .... const double n) {
if (type = FooType::FOO_A) {
...
} else if ....
}
Doesn't seem too bad, but I also don't like having that long parameter list. Seems to easy to make typos that are a pain to debug. So I can
a.) pass a structure in
b.) do something else
and I am just curious about potential b solutions.
Is it possible to templateize this such that I could create a template constructor and call the constructor with something like
std::make_shared<Foo<FooType::FOO_A>>(a, b, c);
Note: I don't want to use inheritance since the rest of the class' functionality has absolutely no use/need for it.
This could be a use case for the named parameters idiom: http://www.cs.technion.ac.il/users/yechiel/c++-faq/named-parameter-idiom.html .
That would allow your constructor call to look like this:
File f = OpenFile("foo.txt")
.readonly()
.createIfNotExist()
.appendWhenWriting()
.blockSize(1024)
.unbuffered()
.exclusiveAccess();
Instead of the above example, you could have a helper class that contains all the named parameters and your class constructor would take an instance of the parameters class as its parameters.
This lets you freely pick the set of parameters that you initialize at construction time. If you want to enforce different subsets being initialized for the different types, then you should just write different constructor versions.
Here is how you could make a templated constructor using a builder pattern:
class Foo {
double a;
int b;
double c;
public:
Foo(double a, int b, char c) {
}
};
template <FooType Type>
class Builder { };
template <>
class Builder<FooType::FOO_A> {
double _a;
public:
Builder& a(double val) { _a = val; return *this; }
Foo build() { return { _a, 0, 0 }; }
};
template <>
class Builder<FooType::FOO_B> {
int _b;
public:
Builder& b(int val) { _b = val; return *this; }
Foo build() { return { 0.0, _b, 0 }; }
};
template <>
class Builder<FooType::FOO_C> {
char _c;
public:
Builder& c(char val) { _c = val; return *this; }
Foo build() { return { 0.0, 0, _c }; }
};
The Builder class is templated as you wanted and the code you were executing in that if else statement, you can execute in builder's constructor or the build function on the instance of Foo you will be returning.
In the example a is relevant for FOO_A, b is relevant for FOO_B and c for FOO_C and other values get initialized to their default value.
This is how you would use it:
int main() {
Foo testA = Builder<FooType::FOO_A>().a(12.5).build();
Foo testB = Builder<FooType::FOO_B>().b(10).build();
Foo testC = Builder<FooType::FOO_C>().c('x').build();
return 0;
}
It is a pretty small example for a builder pattern, but from your example it seems like you are using much more arguments. To add another argument to any of the builder specializations in form Builder& typeName(Type val) { _typeName = val; return *this; } (it should return self reference so these funtions can be chained).
The only way I can get this to compile without issuing a warning on no member a when T==B and so on for T==A is to reinterpret_cast within the if statement blocks and access the non-shared members via a pointer. Is there no way to get around this or hint to the compiler otherwise?
This is gcc 4.8.x
enum Type { A, B};
template<Type T> struct S { };
template<> struct S<A> { int x; int a; };
template<> struct S<B> { int y; int x; int b; };
template<Type T> static void foo(int x)
{
// lots of code
S<T> s;
s.x = someCall();
if (T == A)
{
s.a = 1;
}
else if (T == B)
{
s.y = 2;
s.b = 3;
}
// a bunch of common code
}
Edit: I know about making a dedicated specific functions to handle the specifics but I was hoping to avoid extra boilerplate code.
You may use specialization:
template <Type T> void bar(S<T>&);
template <> void bar(S<A>& s) {s.a = 1;}
template <> void bar(S<B>& s) {s.y = 2; s.b = 3;}
template<Type T> static void foo(int x)
{
// lots of code
S<T> s;
s.x = someCall();
bar(s);
// a bunch of common code
}
if (T == A)
[...]
else if (T == B)
[...]
A, B and T here are compile-time entities, not run-time entities. And yet you are attempting to perform a run-time evaluation of something that is known at compile time. Now sure, you could try to hack up something with a kind of iffy cast (try, and fail), or try some other kind of kludgery, but the code is telling you: you're doing it wrong.
Specializing foo is one way, as may be levarging SFINAE (as with enable_if), but from what little I can see here of your use case, that would be doing it wrong too. That's because the code you look to be implementing is some kind of initialization code, or code that manipulates the internal state of the object being used. In a sense, you're violating the principle of single responsibility.
So move that code to where the responsibility belongs: in the class that's being inited.
template<> struct S<A> { int x; int a; void init() {a=1;} };
template<> struct S<B> { int y; int x; int b; void init() { x=2; y=3; } };
template<Type T> static void foo(int x)
{
// lots of code
S<T> s;
s.x = someCall();
s.init();
// a bunch of common code
}
You could also use a factory class. This would abstract away both the instantiation of the object, and the call to init(), which can take different parameters depending on the ultimate type.
Consider the following example
template<class Type = void> class MyClass
{
public:
double getValue()
{
// if "Type == void" return _x, if "Type != void" return _y
return (/* SOMETHING */) ? (_x) : (_y);
}
protected:
double _x;
static const double _y;
};
What could be the /* SOMETHING */ condition ?
I want to return _x if the template parameter is void, and return _y if not. How to do that ?
First off, you can't return anything because the function return type is void.(fixed)
Second, you can specialize that function to act differently when Type is void:
template<class Type> class MyClass
{
public:
double getValue()
{
return _y;
}
protected:
double _x;
static const double _y;
};
template<>
inline double MyClass<void>::getValue()
{
return _x;
}
You could write using SFINAE:
template<typename Type = void>
class MyClass
{
public:
std::enable_if<std::is_same<Type, void>::value, decltype(_x)> getValue()
{
// if "Type == void" return _x, if "Type != void" return _y
return _x;
}
std::enable_if<!(std::is_same<Type, void>::value), decltype(_y)> getValue()
{
return _y;
}
protected:
double _x;
static const double _y;
};
You can use dynamic casts to test for types. Dynamic casts return null pointers if the cast is made to a different type;
Here's an example.
SomeClass* somePointer = NULL;
somePointer = dynamic_cast<SomeClass*>(someOtherPointer);
if (somePointer)
{
// *someOtherPointer is of type SomeClass
}
else
{
// *someOtherPointer is not of type SomeClass
}
For now main problem is that you defined getValue() as returning void.
But let's skip that.
A function definition in C++ needs to be well defined. This means it needs to have immutable return type and argument list and a name. (There is couple of more attributes I believe but it is not that important here).
You can overload function so you have a couple of definitions with differing argument lists, however the returning type must be the same for all functions with the same name. You can get different returning type if you use templates, and the returning type would be a template argument.
Now to handle different types, there are two ways I believe. One is use templates and specializations.
You could define getValue() as template<T> double getValue(); and then use different specializations to handle different branches of your original getValue. In your example it would be:
//default case
template<typename T> double MyClass<T>::getValue() { return _y; }
//void case
template<> double MyClass<void>::getValue() { return _x; }
The second option is to use RTTI mechanism which allows to determine types of objects in run-time. The the code could like almost exactly like yours. E.g.
double getValue()
{
// if "Type == void" return _x, if "Type != void" return _y
return (typeid(Type) == typeid(void)) ? (_x) : (_y);
}
It all depends whether you can determine Type during compilation or not. The RTTI approach has its drawbacks. If you ever wanted to handle more types RTTI allows you to do it by modifying one function while template approach you would need to add another specialization. I guess its up to one's preferences which path to take... and template are quite nicer when it comes to design.
Edit: Oopsies ... I missed that your class is templatized by the Type. So that should practically remove RTTI apporach out of question. I will leave the answer anyways if anyone ever comes here drawn by the sole title, as I believe it is still a valid way to do it.
Using SFINAE ensures that all the work is done by the compiler, while other options using typeid, dynamic_cast etc, require some run-time costs, which are completely unnecessary (since all the information is available at compile time). In fact, these are extremely bad examples for when best to use such methods.
A possible SFINAE solution is
template<class Type = void> class MyClass
{
public:
typename std::enable_if< std::is_void<Type>::value, double>::type
getValue() { return _x; }
typename std::enable_if<!std::is_void<Type>::value, double>::type
getValue() { return _y; }
protected:
double _x;
static const double _y;
};
I find it sometimes annoying that I have to initialise all POD-types manually. E.g.
struct A {
int x;
/* other stuff ... */
A() : x(0) /*...*/ {}
A(/*..*/) : x(0) /*...*/ {}
};
I don't like this for several reasons:
I have to redo this in every constructor.
The initial value is at a different place than the variable declaration.
Sometimes the only reason I have to implement a constructor is because of this.
To overcome this, I try to use my own types instead. I.e. instead of using int x,y;, I use my own vector struct which also initialize automatically with 0. I also thought about just implementing some simple wrapper types, like:
template<typename T>
struct Num {
T num;
Num() : num(0) {}
operator T&() { return num; }
operator const T&() const { return num; }
T& operator=(T _n) { num = _n; return num; }
/* and all the other operators ... */
};
This basically solves this so far for all cases where I want to init with 0 (that are by far the most often cases for me).
Thanks to James McNellis for the hint: This can also be solved via the boost::value_initialized.
Now, not limited to POD-types:
But sometimes I want to initialise with something different and there are the troubles again because that Num template struct cannot easily be extended to allow that. Basically because I cannot pass floating point numbers (e.g. float) as a template parameter.
In Java, I would just do:
class A {
int x = 42;
/*...*/
public A() {}
public A(/*...*/) { /*...*/ }
public A(/*...*/) { /*...*/ }
/*...*/
}
I find it quite important that in such cases where you want to init a member variable always in the same way in all possible constructors, that you are able to write the init value directly next to the member variable, like in int x = 42;.
So the thing I was trying to solve is to do the same thing in C++.
To overcome the problem that I cannot pass the init-value via a template parameter, I hacked together an ugly macro:
#define _LINENAME_CAT( name, line ) name##line
#define _LINENAME( name, line ) _LINENAME_CAT( name, line )
/* HACK: use _LINENAME, workaround for a buggy MSVC compiler (http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=360628)*/
#define PIVar(T, def) \
struct _LINENAME(__predef, __LINE__) { \
typedef T type; \
template<typename _T> \
struct Data { \
_T var; \
Data() : var(def) {} \
}; \
Data<T> data; \
T& operator=(const T& d) { return data.var = d; } \
operator const T&() const { return data.var; } \
operator T&() { return data.var; } \
}
(For other compilers, I can just omit that _LINENAME name for the struct and just leave it unnamed. But MSVC doesn't like that.)
This now works more or less like I want it. Now it would look like:
struct A {
PIVar(int,42) x;
/*...*/
A() {}
A(/*...*/) { /*...*/ }
A(/*...*/) { /*...*/ }
/*...*/
};
While it does what I want (mostly), I still am not fully happy with it:
I don't like the name PIVar (which stands for PreInitVar) but I really couldn't come up with something better. At the same time, I want to have it short.
I don't like that macro hack.
How have you solved this? Any better solution?
There was an answer which was deleted again which said that C++0x allows basically the same syntax as in Java. Is that true? So then I would just have to wait for C++0x.
Please don't give any comments like:
"then just use Java instead" / "don't use C++ then" or
"if you need something like this, you are probably doing something wrong" or
"just don't do it this way".
Also, please don't tell me not to use it. I know about all the drawbacks of my current solution. Please only make comments about non-obvious drawbacks if you are really sure that I am not aware of that. Please don't just state that there are many drawbacks in my current solution. Please also don't state that it is not worse to use it. I am just asking if you know about a better solution than the one I have presented here.
Sometimes the only reason I have to implement a constructor is because of this.
You don't have to do that.
struct POD {
int i;
char ch;
};
POD uninitialized;
POD initialized = POD();
Equally in an initialization list:
class myclass
POD pod_;
// ....
myclass()
: pod_() // pod_'s members will be initialized
{
}
To overcome this, I try to use my own types instead.
Your type fails in this scenario:
void f(int&);
Num<int> i;
f(i);
There's likely more problems, but this is what occurred to me immediately.
How have you solved this? Any better solution?
Yes, we all have solved this. We did by not attempting to fight the language, but to use it the way it was created: initialize PODs in initialization lists. When I see this:
struct ML_LieroX : MapLoad {
std::string id;
PIVar(int, 0) type;
std::string themeName;
PIVar(int, 0) numObj;
PIVar(bool,false) isCTF;
I cringe. What is this doing? Why is it this way? Is this even C++?
All this just to save a few keystrokes typing an initialization list? Are you even serious?
Here's an old bon mot: A piece of code gets written once, but over its lifetime will be read tens, hundreds, or even thousands of times. That means that, in the long run, the time it takes to write a piece code is more or less neglectable. Even if it takes you ten times as long to write the proper constructors, but it saves me 10% of the time necessary to understand your code, then writing the constructors is what you should do.
Boost provides a value_initialized<T> template that can be used to ensure an object (POD or not) is value-initialized. Its documentation goes into great detail explaining the pros and cons of using it.
Your complaint about not being able to automatically initialize an object to a given value doesn't make much sense; that has nothing to do with the object being POD; if you want to initialize a non-POD type with a non-default value, you have to specify the value when you initialize it.
You could initialize POD structures as follows:
struct POD
{
int x;
float y;
};
int main()
{
POD a = {}; // initialized with zeroes
POD b = { 1, 5.0f }; // x = 1, y = 5.0f
return 0;
}
There is a proposal for C++0x which allows this:
struct A {
int x = 42;
};
That is exactly what I want.
If this proposal is not making it into the final version, the possibility of delegating constructors is another way of at least avoiding to recode the initialization in every single constructor (and at the same time avoiding a dummy helper function to do this).
In current C++, there does not seem to be any better way to do it despite what I have already demonstrated.
C++ does have constructor delegation, so why not use it?
struct AState
{
int x;
AState() : x(42) {}
};
class A : AState
{
A() {}
A(/*...*/) { /*...*/ }
A(/*...*/) { /*...*/ }
};
Now initialization of x is delegated by all constructors. The base constructor can even accept arguments passed from each version of A::A.
Prior to C++0x there is a solution which works well if the non-zero value you want to initialize with is not completely arbitrary (which is usually the case in practice). Similar to boost::initialized_value but with an extra argument to take the initial value (which gets a little fussy because C++).
template<typename T> struct Default { T operator()() { return T(); } };
template<typename T, T (*F)()> struct Call { T operator()() { return F(); } };
template<int N> struct Integer { int operator()() { return N; } };
template< typename X, typename Value = Default<X> >
class initialized {
public:
initialized() : x(Value()()) {}
initialized(const X& x_) : x(x_) {}
const X& get() const { return x; }
operator const X&() const { return x; }
operator X&() { return x; }
private:
X x;
};
You might use it like this:
struct Pi { double operator()() { return 3.14; } }; //Exactly
const char* init_message() { return "initial message"; }
Point top_middle() { return Point(screen_width()/2, 0); }
struct X {
initialized<int> a;
initialized<int, Integer<42> > b;
initialized<double> c;
initialized<double, Pi> d;
initialized<std::string> e;
initialized<std::string, Call<const char*, init_message> > f;
initialized<Point> g;
initialized<Point, Call<Point,top_middle> > h;
X() {}
};
I find the annoyance of having to create a dummy function to return any non-integral / non-default value is generally amortized across the entire library (since the non-zero initial values for a particular type are generally shared by many classes).
Obviously typedef is a friend here.
Anyway, can't wait to upgrade to C++0x/11/14/whatever.
Ok, it's been a while since I wrote in C++.
and I've never done anything quiet this high level.
So basically I need to create a class.
The constructor for the class needs to take a reference (or pointer) to a method form another class, or to a function.
Basically I have a class that needs to on occasion read a value from a fltk valuator (version 1.1.x), and then change some stuff about itself.
Each object will have it's own valuator associated with it.
(they also have a link to another object of the same parent, which after updating them selves from the valuator will tell to update, and so on)
So how do i pass functions around, in constructors?
Here is an example where a method of Foo is passed to the Bar constructor and later invoked on a given Bar object:
struct Foo
{
int z;
int add(int x, int y)
{
return x + y + z;
}
int mul(int x, int y)
{
return x * y * z;
}
};
typedef int (Foo::*foo_method)(int, int);
struct Bar
{
foo_method m;
Bar(foo_method m) : m(m) {}
int call_on(Foo* foo)
{
return (foo->*m)(4, 2);
}
};
int main()
{
Bar bar(&Foo::add);
Foo foo = { 123 };
bar.call_on(&foo);
}
If, on the other hand, you already know the Foo object at Bar construction time, then Bar does not really care which class the method belongs to. All it needs is a functor to call later, and the Foo object can simply be bound by the client.
#include <functional>
struct Bar
{
std::function<int (int, int)> f;
Bar(std::function<int (int, int)> f) : f(f) {}
int call()
{
return f(4, 2);
}
};
using namespace std::placeholders;
int main()
{
Foo foo = { 123 };
Bar bar(std::bind(&Foo::add, &foo, _1, _2));
bar.call();
}
If you don't have a C++0x compiler, replace std::bind with std::tr1::bind or boost::bind.
Your constructor might look something like this:
// convenient typedef. This is for a pointer to a function in Foo
// The function returns void and takes no parameters.
typedef void (Foo::*FooPtr)();
class Bar {
public:
Bar (FooPtr foo_ptr);
};
Check out some web references for more details on the syntax for pointer-to-members. It's a lot easier if you get familiar with it first.
As an additional note, check out the functions mem_fun and mem_fun_ref. These may do what you need.
The easiest way to capture this is with boost::function. It can store function pointers, but also the result of binding a member function to an object.
For instance,
class Foo {
Foo(boost::function<int(void)>);
};
will allow you to accept any source of integers.