I am fairly new to C++ (using C++ 2011) and I would like to find a solution for the following problem. I have a class that represents a fonction:
class Curve {
private:
...
public:
std::array<double, 3> value(double s);
}
I am using that object to pass this function to an algorithm that is represented by a class:
template <int n, typename Functor>
class Algorithm {
private:
Functor f;
std::array<double, n> a;
public:
...
}
Then I create the object
Algorithm<3, Curve> solver;
But the 3 is obviously the 3 coming from the size of the array returned by the method value of any objet of type Curve. I would like to simplify this code so that I can use :
Algorithm<Curve> solver;
But I have no idea on how to do that. Would you mind giving me a hint ?
Best regards,
Francois
Add a member array_length or something similar to the Curve like classes:
class Curve
{
public:
static constexpr const std::size_t length = 3;
private:
std::array<double,length> a;
};
template<typename ALGORITHM , std::size_t n = ALGORITHM::length>
class Algorithm
{
...
};
If you need to allow classic function entities as algorithms, that approach doesn't work since there is no length member. Other way could be to create a metafunction data_length
which given a algorithm function F returns the length of the data:
template<typename F>
struct length;
//Specialization for Curve class:
template<>
struct length<Curve> : public std::integral_constant<std::size_t,3>
{};
And then:
template<typename F , std::size_t n = length<F>::value>
struct Algorithm
{
...
};
EDIT: Like in any other template, to implement the method specify its template parameters:
template<typename F , std::size_t N>
void Algorithm<F,N>::execute()
{
_f();
}
Here is a running example.
Use decltype to get the return type of value, and std::tuple_size to find out how big it is (Live at Coliru):
template <typename Functor>
class Algorithm {
private:
Functor f;
static const std::size_t n =
std::tuple_size<decltype(f.value(0.))>::value;
std::array<double, n> a;
public:
// ...
};
or if you simply want a to have the same type that value returns:
template <typename Functor>
class Algorithm {
private:
Functor f;
decltype(f.value(0.)) a;
public:
// ...
};
or if you might someday want to use functions of a different type - say int or long long or whatever - you can ask for the return type of f.value when invoked with a default-constructed value of whatever its argument type happens to be:
template <typename Functor>
class Algorithm {
private:
Functor f;
decltype(f.value({})) a;
public:
// ...
};
You could "pass" the 3 in an enum member like this:
class Curve {
public:
enum { arity = 3 };
std::array<double, arity> value(double s);
};
template <typename Functor>
class Algorithm {
private:
std::array<double, Functor::arity> a;
};
Curve curve;
Algorithm<Curve> solver;
Related
Let's say I have a base class foo and two derived classes A and B. I then have another class bar, which has a data members x, y, z, which can be either A,or, but the types depends on other data members x_type, y_type, and z_type, and those values are not available at compile time. I though about using template data member and defining the type in constructor, where I get the values for the types but apparently that is not possible at least in C++11. So how to proceed?
class foo{
public:
foo(double);
int x_type;
virtual double do_something(double, int) = 0;
};
class A: public foo {
public:
A(double, double);
double do_something(double, int);
private:
double z1;
double z2;
};
class B: public foo {
public:
B(double);
double do_something(double, int);
private:
double w;
};
class bar {
public:
bar();
double do_something2(int);
private:
int x_type;
int y_type;
int x_type;
x; // these are either A or B...
y;
z;
};
And in constructor I would have something like
if(x_type == 1){
x = A(arg1, arg2);
} else {
x = B(arg3);
}
In my real application there can be much higher number of derived classes and data members with unknown types. I was wondering if it is possible to make bar a template class with multiple template parameters, but I am not sure if that is possible either as the parameter type depends on another parameter?
You need to use polymorphism and take advantage of the common base class Foo:
private:
int x_type;
int y_type;
int x_type;
std::unique_ptr<Foo> x; // these are either A or B...
std::unique_ptr<Foo> y;
std::unique_ptr<Foo> z;
};
Then in your constructor you can create x y z from the correct type:
if(x_type == 1){
x.reset(new A(arg1, arg2));
} else {
x.reset(new B(arg3));
}
It is a good practice to move the code that creates the correct Foo instance in a so called "factory" class or function in order to hide the decision making logic and construction specifics (which might be quite complex at times).
If all type that can be used for x, y and z are all derived from a common base class, the base-pointer solution, with std::unique_ptr (+1 for Lyubomir Stankov), is (IMHO) a good solution.
But you asked "if it is possible to make bar a template class with multiple template parameters".
Yes: it's possible. Not really elegant (ever IMHO) but possible.
I propose the following solution for fun but I think that, in a more general case (note that, in my example, A and B are unrelated classes, not more derived from foo), can be useful (I hope so)
#include <tuple>
#include <string>
#include <utility>
class A
{
private:
double d;
std::string s;
public:
A (double d0, std::string s0) : d { d0 }, s { s0 } { }
};
class B
{
private:
long l;
public:
B (long l0) : l { l0 } { }
};
template <typename Tx, typename Ty, typename Tz>
class bar
{
private:
template <typename ... Ts>
using tpl = std::tuple<Ts...>;
template <std::size_t ... Is>
using is = std::index_sequence<Is...> const;
template <std::size_t N>
using mis = std::make_index_sequence<N>;
Tx x;
Ty y;
Tz z;
template <typename ... Tsx, std::size_t ... Isx,
typename ... Tsy, std::size_t ... Isy,
typename ... Tsz, std::size_t ... Isz>
bar (tpl<Tsx...> const & tx0, is<Isx...> const &,
tpl<Tsy...> const & ty0, is<Isy...> const &,
tpl<Tsz...> const & tz0, is<Isz...> const &)
: x { std::get<Isx>(tx0) ... },
y { std::get<Isy>(ty0) ... },
z { std::get<Isz>(tz0) ... }
{ }
public:
template <typename ... Tsx, typename ... Tsy, typename ... Tsz>
bar (tpl<Tsx...> const & tx0,
tpl<Tsy...> const & ty0,
tpl<Tsz...> const & tz0)
: bar(tx0, mis<sizeof...(Tsx)> {},
ty0, mis<sizeof...(Tsy)> {},
tz0, mis<sizeof...(Tsz)> {})
{ }
};
int main()
{
bar<A, B, A> aba{ std::make_tuple(2.3, "str1"),
std::make_tuple(4),
std::make_tuple(5.4, "str2") };
bar<B, A, B> bab{ std::make_tuple(3),
std::make_tuple(3.2, "str3"),
std::make_tuple(5) };
}
Unfortunately this example use std::make_index_sequence and std::index_sequence that are C++14 features.
If you want implement foo in C++11, you can implement the following structs struct indexSeq and struct indexSeqHelper, to substitute std::index_sequence and std::make_index_sequence
template <std::size_t ...>
struct indexSeq
{ };
template <std::size_t N, std::size_t ... Next>
struct indexSeqHelper
{ using type = typename indexSeqHelper<N-1U, N-1U, Next ... >::type; };
template <std::size_t ... Next >
struct indexSeqHelper<0U, Next ... >
{ using type = indexSeq<Next ... >; };
and define is and mis as follows
template <std::size_t ... Is>
using is = indexSeq<Is...>;
template <std::size_t N>
using mis = typename indexSeqHelper<N>::type;
The static type of all variables must be known at compile time, so it cannot change based on the value of a run time object. The way to make this work is to make x, y, and z all have the type std::uniqe_ptr<foo> and then dynamically allocate an A or B object at run time:
class bar {
public:
bar(some_type something) {
if (something == some_value) {
b.x = new A(3.14, 12.34);
} else {
b.x = new B(456.78);
}
}
private:
int x_type;
std::unique_ptr<foo> x;
//...
};
int main() {
bar b(whatever());
}
In this case you should also declare foo::~foo() to be virtual so that you ensure the derived objects get destroyed correctly.
It would also be a generally Good Idea™ to eliminate x_type and friends entirely and write code that doesn't care about the actual type of x once it's created.
I was wondering if it is possible to make bar a template class with multiple template parameters, but I am not sure if that is possible either as the parameter type depends on another parameter?
I don't know if this helps, but I'll let it here just in case.
You see, different specializations of a template can inherit from different classes. So that you can have:
// fwd decl
template <int kind> class bar;
template <> class bar<1> : public A {
public:
bar(double x, double y) : A(x,y) { }
};
template <> class bar<2> : public B {
public:
bar(double a) : B(a) { }
};
At later stage, when you come with a class C : public foo, you just assign another kind to a new bar template specializations and there you have it: using bar as a unifying name (warning... but not a unifying type - not other than the common foo ancestor. bar<1> and bar<2> will be two different types)
So, Ok, if you don't want inheritance, you can have it by different has-a in specific bar template specializations.
Like
template <int kind> class bar;
template <> class bar<1> {
A val;
public:
bar(double x, double y) : val(x,y) { }
void doSomething2(...) {
// use the val of type A
}
};
template <> class bar<2> {
B val;
double y_;
public:
bar(double x, double y) : val(x), y_(y) { }
void doSomething2(...) {
// use the val of type B and a separate y_
}
};
I though about using template data member and defining the type in
constructor, where I get the values for the types but apparently that
is not possible at least in C++11
C++11 comes with the standard schema of dealing with templated construction depending on some parameter by using make_* template function creating appropriate type of object. See e.g. make_tuple function:
auto t = std::make_tuple(1, "abc", 1.0);
// decltype(t) == std::tuple<int, char const*, double>
This can be implemented by creating template class and template construction function:
template <class T>
struct foo {
T t;
foo(T t): t(t) { }
};
template <class T>
foo<T> make_foo(T t) { return foo<T>(t); }
Now I have a template class
template <class T>
class b
{
void someFunc() {
T t;
t.setB();
}
};
I know the template T only will be instantiated into 2 classes.
class D
{
public:
void setB();
};
class R
{
public:
void SetB();
};
As we can see, class D's function name setB is not the same as R's function SetB. So in template class b I cannot only just use setB. So is there some method if I cannot revise D or R? Can I add some wrapper or trick into the template class to solve this problem?
Maybe a trait class can help you:
struct Lower {};
struct Upper {};
// trait for most cases
template <typename T>
struct the_trait {
typedef Lower Type;
};
// trait for special cases
template <>
struct the_trait<R> {
typedef Upper Type;
};
template <class T>
class b {
public:
void foo() {
foo_dispatch(typename the_trait<T>::Type());
}
private:
void foo_dispatch(Lower) {
T t;
t.setB();
}
void foo_dispatch(Upper) {
T t;
t.SetB();
}
};
As #Arunmu pointed, this technique is also known as Tag Dispatching.
You can specialise your template for the class that has different semantics:
template<>
class b<R>
{
void doWork() {
R obj;
obj.SetB();
// or R::SetB() if it was a static method.
}
};
Instead of using self programmed traits you can also check for the existence of a function with SFINAE.
If you want to switch your called method only one of them must exist in each class. My method provided will not work if the check find more then one of the tested methods!
The following example is written for C++14 but can also be used with c++03 if you replace the new library functions with self implemented ones ( which is of course not convenient )
The testing class has_Foo and has_Bar can also be embedded in a preprocessor macro, but I wrote it expanded to makes the things easier to read.
How it works and why there are some more intermediate steps are necessary are explained in the comments. See below!
#include <iostream>
// First we write two classes as example. Both classes represents
// external code which you could NOT modify, so you need an
// adapter to use it from your code.
class A
{
public:
void Foo() { std::cout << "A::Foo" << std::endl; }
};
class B
{
public:
void Bar() { std::cout << "B::Bar" << std::endl; }
};
// To benefit from SFINAE we need two helper classes which provide
// a simple test functionality. The solution is quite easy...
// we try to get the return value of the function we search for and
// create a pointer from it and set it to default value nullptr.
// if this works the overloaded method `test` returns the data type
// one. If the first test function will not fit, we cat with ... all
// other parameters which results in getting data type two.
// After that we can setup an enum which evaluates `value` to
// boolean true or false regarding to the comparison function.
template <typename T>
class has_Foo
{
using one = char;
using two = struct { char a; char b;};
template <typename C> static one test( typename std::remove_reference<decltype(std::declval<C>().Foo())>::type* );
template <typename C> static two test( ... ) ;
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
enum { Yes = sizeof(test<T>(0)) == sizeof(one) };
enum { No = !Yes };
};
template <typename T>
class has_Bar
{
using one = char;
using two = struct { char a; char b;};
template <typename C> static one test( typename std::remove_reference<decltype(std::declval<C>().Bar())>::type* );
template <typename C> static two test( ... ) ;
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
enum { Yes = sizeof(test<T>(0)) == sizeof(one) };
enum { No = !Yes };
};
// Now in your adapter class you can use the test functions
// to find out which function exists. If your class
// contains a Foo function the first one compiles and if the
// the class contains a Bar function the second one fits. SFINAE
// disable the rest.
// We need a call helper here because SFINAE only
// fails "soft" if the template parameter can deduced from the
// given parameters to the call itself. So the method
// Call forwards the type to test "T" to the helper method as
// as explicit parameter. Thats it!
template <typename T>
class X: public T
{
public:
template < typename N, std::enable_if_t< has_Foo<N>::value>* = nullptr>
void Call_Helper() { this->Foo(); }
template < typename N, std::enable_if_t< has_Bar<N>::value>* = nullptr>
void Call_Helper() { this->Bar(); }
void Call() { Call_Helper<T>(); }
};
int main()
{
X<A> xa;
X<B> xb;
xa.Call();
xb.Call();
}
I have some conceptual problem in a class hierarchy, where the Base class depends on a fixed scalar type T, but the derived CRTP'ed classes use return value type deduction.
For example, consider the following class hierarchy:
template<typename ... Args> struct VectorBase;
template<typename T>
struct VectorBase<T>
{
virtual T eval(int) const = 0;
auto operator[](int i) {return this->eval(i);}
};
template<typename T, typename Derived>
struct VectorBase<T, Derived> : public VectorBase<T>
{
virtual T eval(int i) const override final { return this->operator[](i); }
auto operator[](int i) const
{
return static_cast<Derived const&>(*this).operator[](i);
}
};
template<typename T>
struct Vector : public VectorBase<T, Vector<T> >
{
//just for code shortness,
//in reality there is a container which returns the corresponding elements
auto operator[](int i) const { return T{}; }
};
template<typename VectorType>
struct SomeTransformation : public VectorBase< /* ... what to write here generically? */ double, SomeTransformation<VectorType> >
{
VectorType const& v;
SomeTransformation(VectorType const& _v) : v(_v) {}
auto operator[](int i) const
{
//do something with vector v and return i-th element, e.g.
return v[i]*0.1;
}
};
DEMO
Now, given a specific vector with value type int, say, one can apply SomeTransformation and get a vector of value type double. Moreover, I can be sure that SomeTransformation derives from VectorBase<double>, so that, for example, I can't falsely assign it to a VectorBase<int>-pointer:
int main()
{
Vector<int> v;
std::cout<<typeid(decltype(v[0])).name()<<std::endl; //prints "i" for int
auto u = SomeTransformation<decltype(v)>(v);
std::cout<<typeid(decltype(u[0])).name()<<std::endl; //prints "d" for double
//works
std::unique_ptr<VectorBase<double> > ud = std::make_unique<SomeTransformation<decltype(v)> >(v);
//gives a compile-time error, which is good
//std::unique_ptr<VectorBase<int> > ui = std::make_unique<SomeTransformation<decltype(v)> >(v);
}
Now for the problem: in the scalar type argument of SomeTransformation, where I wrote /* ... what to write here generically? */, I really would want to write something like
template<typename VectorType>
struct SomeTransformation :
public VectorBase<decltype(std::declval<SomeTransformation<VectorType> >().operator[](0)), SomeTransformation<VectorType> >
{
//...
};
in order to deduce the value type of the transformation automatically and propagate this type down to the base class. However, this doesn't seem to work, which I think is because the base classes are instantiated before the derived class ... so the class of which I want to deduce the type doesn't exists yet.
Is there any way to obtain this behaviour without breaking the inheritance hierarchy?
I figured out a possible alternative by myself and want to bring it up for discussion.
One could for instance add a type parameter T also to the derived class and then use a dummy type in order to instantiate this class once. With this, it is possible to deduce the return type of the so-created class, which is used in a next step to instantiate the class to be really used.
Example:
namespace detail
{
template<typename T, typename VectorType>
struct SomeTransformation :
public VectorBase<T, SomeTransformation<T, VectorType> >
{
//the same as above
};
}
struct DummyType
{
//make any type convertible to DummyType
template<typename T> DummyType(T const&) {}
};
template<typename VectorType>
using SomeTransformationValueType =
decltype(std::declval<detail::SomeTransformation<DummyType, VectorType> >().operator[](0));
template<typename VectorType>
using SomeTransformation =
typename detail::SomeTransformation<SomeTransformationValueType<VectorType>, VectorType>;
DEMO
Consider the following code:
/* aclass.h */
class AClass
{
public:
template<size_t N, class Vector>
void aMethod(const Vector &);
};
/* aclass.inl */
// method for any N
template<size_t N, class Vector>
void AClass::aMethod(const Vector &) { ... }
// method for N = 1
template<class Vector>
void AClass::aMethod<1>(const Vector &) { ... }
/* main.cpp */
int main()
{
AClass inst;
std::vector<float> data;
// calls method for any N
inst.aMethod<20>(data);
// calls method for N = 1
inst.aMethod<1>(data);
}
I can't seem to find the correct syntax for specializing a single template argument of integer type - and not even sure if it is legal. I looked around a bit, but didn't find anyone with this problem...
These are the errors i get (from msvc):
error C2244 : 'AClass::aMethod' : unable to match function definition to an existing declaration
error C2768 : 'AClass::aMethod' : illegal use of explicit template arguments
How would i go on about solving this problem?
There ain't no such thing as a partial specialization of a function template.
To achieve your goal, you could go through a helper class, which can be partially specialized:
class AClass;
template<size_t N, class Vector>
struct AMethodHelper {
static void Do(AClass* pThis, const Vector&) {
// General for N != 1
}
};
template<class Vector>
struct AMethodHelper<1, Vector> {
static void Do(AClass* pThis, const Vector&) {
// Special for N == 1
}
};
class AClass
{
public:
template<size_t N, class Vector>
void aMethod(const Vector & v) {
AMethodHelper<N, Vector>::Do(this, v);
}
};
Or, you could use two overloads selected with SFINAE:
class AClass
{
public:
template<size_t N, class Vector>
typename enable_if<N!=1>::type aMethod(const Vector &) {
// General for N != 1
}
template<size_t N, class Vector>
typename enable_if<N==1>::type aMethod(const Vector &) {
// Special for N == 1
}
};
Or, I suppose, you could just have one method with if (N == 1) inside. I suspect any decent compiler would be smart enough to eliminate dead code in any given instantiation.
There two unrelated structures A and B
template <typename T>
struct A {};
template <typename T>
struct B {};
one enum type
typedef enum { ma, mb} M;
and class C containing function templates
class C
{
public:
template <typename T>
static void f1 ( A <T> &a) {}
template <typename T>
static void f2 ( B <T> &b) {}
template <typename U>
static void algo (U &u, M m)
{
/*Long algorithm here
....
*/
if ( m == ma) f1(u);
else f2(u);
}
};
Static method algo contains some algorithm, that is quite difficult... It modified some values and results into structure A or B.
I would like to run static method algo with objects A or B depending on M value. But how to say it to my compiler :-)
int main()
{
A <double> a;
C::algo (a, ma); //Error
}
Error 1 error C2784: 'void C::f1(A<T>)' : could not deduce template argument for 'A<T>' from 'B<T>
A] I was thinking about pointer to function, but they are not usable with function templates.
B] Maybe a compile polymorphism could help
template <typename U, M m>
static void algo (U &u, M <m> ) { ...} //Common for ma
template <typename U, M m>
static void algo (U &u, M <mb> ) { ...} //Spec. for mb
But this solution has one big problem: Both implementations should unnecessarily include almost the same code (why to write the algorithm twice?).
So I need one function algo() processing both types of arguments A and B. Is there any more comfortable solution?
It seems that you are using the enum to convey type information from the user. I would suggest that you don't.
In the simplest case if f1 and f2 are renamed f, then you can remove the if altogether and just call it. The compiler will call the appropriate overload for you.
If you cannot or don't want to rename the function templates, then you can write a helper template that will dispatch for you (basic class template undefined, specialisations for A and B that dispatch to the appropriate static function)
If the enum is used for something else (that the compiler cannot resolve for you), you can still pass it around and rewrite the helper to dispatch on the enum rather than the type of the argument and you will have to rewrite the code to have the enum value as a compile time constant (simplest: pass it as template argument to algo). In this case ou can write function specialisations instead of classes if you want, as they would be full specialisations. But note that if you can avoid having to pass it you will remove a whole family of errors: passing the wrong enum value.
// Remove the enum and rename the functions to be overloads:
//
struct C { // If everything is static, you might want to consider using a
// namespace rather than a class to bind the functions together...
// it will make life easier
template <typename T>
static void f( A<T> & ) { /* implement A version */ }
template <typename T>
static void f( B<T> & ) { /* implement B version */ }
template <typename T> // This T is either A<U> or B<U> for a given type U
static void algo( T & arg ) {
// common code
f( arg ); // compiler will pick up the appropriate template from above
}
};
For the other alternatives, it is easier if the enclosing scope is a namespace, but the idea would be the same (just might need to fight the syntax a bit harder:
template <typename T>
struct dispatcher;
template <typename T>
struct dispatcher< A<T> > {
static void f( A<T>& arg ) {
C::f1( arg );
}
};
template <typename T>
struct dispatcher< B<T> > {
static void f( B<T>& arg ) {
C::f2( arg );
}
};
template <typename T>
void C::algo( T & arg ) {
// common code
dispatcher<T>::f( arg );
}
Again, getting this to work with a class might be a bit trickier as it will probably need a couple of forward declarations, and I don't have a compiler at hand, but the sketch should lead you in the right direction.
Normal function overloading is sufficient:
template <typename T>
static void f1 ( A <T> &a) {}
template <typename T>
static void f2 ( B <T> &b) {}
template <typename T>
static void algo (A<T>& u) {
f1(u);
}
template <typename T>
static void algo (B<T>& u) {
f2(u);
}
And then:
A<int> a;
Foo::algo(a);
Although it's not clear what you stand to gain from such an arrangement.
If you realy need to do that in one function, you can use typetraits:
template<typename T, T Val>
struct value_type { static const T Value = Val; };
struct true_type : public value_type<bool, true>{};
struct false_type : public value_type<bool, false>{};
template<class T>
struct isClassA : public false_type{};
template<>
struct isClassA<A> : public true_type{};
template < typename T >
void Algo( T& rcT )
{
if ( true == isClassA<T>::Value )
{
// Class A algorithm
}
else
{
// Other algorithm
}
};
the value of m parameter is unknown until runtime, so the compiler has to generate code for both if (m == ma) and else branches when it specialize the function.
It then complains since it can't understand what he should do if you happen to call C::algo(a,mb) or similar.
As Jon suggested, overloading should fix your case, try using this code:
template<typename U>
static void f12(A<U>&u) { f1(u); }
template<typename U>
static void f12(B<U>&u) { f2(u); }
template<typename U>
static void algo(U& u, M m)
{
/* long algorithm here
...
*/
//use overloading to switch over U type instead of M value
f12(u);
}
Also you can use function pointers with template functions, as long as you specify the template parameters:
template<typename U>
static void algo(U& u, M m, void(*)(U&) func)
{
/* ... */
(*func)(u);
}
int main()
{
A <double> a;
C::algo (a, ma, &C::f1<double> );
}