template<class T>
struct gSorting : public std::binary_function<T, T,bool> {
bool operator() (int number, int n2)
{
cout << "int" << endl;
return (number<n2);
}
bool operator() (double number, double n2)
{
cout << "double" << endl;
return (number<n2);
}
bool operator() (const MYClass& obj1, const MYClass& obj2)
{
return (obj1.element<obj2.element);
}
};
int main () {
gSorting<int> sorting_object;
std::cout << std::boolalpha << sorting_object (2.0f, 4.3f) << ".\n";
std::getchar();
return 0;
}
is there any problem with this code? is it that generic? or is there better way to do a generic sorting algorithm to include all of my classes used
it compiles, the output pointed to the double which is good, however how can I make it a template, but dont have to specify the input type in the declaration?
gSorting< int > sorting_object;
-------------^^^^ we dont need any specific type? am I right
output:
I would personally define a class template for the binary predicate and specialize it as needed, e.g.:
template <typename T>
struct gSorting
: std::binary_function<T const&, T const&, bool> // not really needed
{
bool operator()(T const& t0, T const& t1) const {
return t0 < t1;
}
};
template <>
struct gSorting<MyClass>
: std::binary_function<MyClass const&, MyClass const&, bool>
{
bool operator()(MyClass const& c0, MyClass const& c1) const {
return c0.element < c1.element;
}
};
In a real implementation, the argument type for the generic version should probably decide whether the argument is passed by value or by const& depending on the kind of type and/or based on a trait which is then specialized as needed. For example:
template <typename T>
struct argument_type
{
typedef typename std::conditional<
std::is_fundamental<T>::value, T, T const&>::type type;
};
template <typename T>
struct gSorting
: std::binary_function<typename argument_type<T>::type,
typename argument_type<T>::type, bool>
{
typedef typename argument_type<T>::type arg_type;
bool operator()(arg_type t0, arg_type t1) const {
return t0 < t1;
}
};
Related
I have a pretty specific situation where I'm feeding a bunch of data to a hasher-like class. In particular, one data type that I use has a member whose type depends on the supertype's type parameter. Long story short, here's a piece of code that illustrates this behaviour :
#include <assert.h>
#include <iostream>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
// Some dummy priority structs to select overloads
struct priority0 { };
struct priority1 : priority0 { };
// This is the hasher-like function
struct Catcher
{
// Ideally we feed everything to this object through here
template <typename T> Catcher& operator<<(const T& v)
{
add(v, priority1{}); // always attempt to call the highest-priority overload
return *this;
}
// For floating-point data types
template <typename T> auto add(const T& v, priority1) -> std::enable_if_t<std::is_floating_point_v<T>, void>
{
std::cout << "caught float/double : " << v << std::endl;
}
// For ranges
template <class T> auto add(const T& range, priority1) -> decltype(begin(range), end(range), void())
{
for(auto const& v : range)
*this << v;
}
// For chars
void add(char c, priority1)
{
std::cout << c;
std::cout.flush();
}
// When everything else fails ; ideally should never happen
template <typename T> void add(const T& v, priority0)
{
assert(false && "should never happen");
}
};
// The one data type. Notice how the primary template and the
// specialization have a `range` member of different types
template <class T> struct ValueOrRange
{
struct Range
{
T min;
T max;
};
Range range;
T value;
};
template <> struct ValueOrRange<std::string>
{
std::vector<std::string> range;
std::string value;
};
// Overload operator<< for Catcher outside of the
// class to allow for processing of the new data type
// Also overload that for `ValueOrRange<T>::Range`. SFINAE should make sure
// that this behaves correctly (?)
template <class T> Catcher& operator<<(Catcher& c, const typename ValueOrRange<T>::Range& r)
{
return c << r.min << r.max;
}
template <class T> Catcher& operator<<(Catcher& c, const ValueOrRange<T>& v)
{
return c << v.range << v.value;
}
int main(int argc, char *argv[])
{
ValueOrRange<std::string> vor1{{}, "bleh"};
ValueOrRange<float> vor2{{0.f, 1.f}, 0.5f};
Catcher c;
c << vor1; // works fine, displays "bleh"
c << vor2; // fails the assert in Catcher::add(const T&, priority0) with T = ValueOrRange<float>::Range
return 0;
}
While the line c << vor1 gets resolved correctly through the various overloads and has the intended effect, the second line c << vor2 fails the assert.
What I want to happen : c << vor2 calls Catcher& operator<<(Catcher& s, const ValueOrRange<float>& v), which in turn calls Catcher& operator<<(Catcher& s, const typename ValueOrRange<float>::Range& r)
What does happen : instead of Catcher& operator<<(Catcher& s, const typename ValueOrRange<float>::Range& r), it is Catcher& Catcher::operator<<(const T& v) with T = typename ValueOrRange<float>::Range that is called, and thus the assert fails.
Worthy of note is that this same code has the intended effect on MSVC, and fails the assert on GCC.
Any idea on how I should fix that ?
Thanks to feedback from Igor Tandetnik, I got rid of the ::Range-specific overload and simply went for checking std::is_same_v<T, std::string>. A little less modular than I'd like, but it'll do the trick.
// A single function will do the trick
template <class T> Catcher& operator<<(Catcher& c, const ValueOrRange<T>& v)
{
if constexpr (std::is_same_v<T, std::string>)
c << v.range;
else
c << v.range.min << v.range.max;
return c << v.value;
}
In Catcher& operator<<(Catcher& c, const typename ValueOrRange<T>::Range& r), T in non deducible.
One work around would be friend function:
template <class T> struct ValueOrRange
{
struct Range
{
T min;
T max;
friend Catcher& operator<<(Catcher& c, const Range& r)
{
return c << r.min << r.max;
}
};
Range range;
T value;
};
Demo
I have this code:
template<class T1, class T2>
class Pair
{
private:
T1 first;
T2 second;
public:
void SetFirst(T1 first)
{
this.first = first;
}
void SetSecond(T2 second)
{
this.second = second;
}
T1 GetFirst()
{
return first;
}
T2 GetSecond()
{
return second;
}
};
How could I implement two single methods SetValue() and GetValue(), instead of the four I have, that decides depending on parameters which generic type that should be used? For instance I'm thinking the GetValue() method could take an int parameter of either 1 or 2 and depending on the number, return either a variable of type T1 or T2. But I don't know the return type beforehand so is there anyway to solve this?
Not sure to understand what do you want and not exactly what you asked but...
I propose the use of a wrapper base class defined as follows
template <typename T>
class wrap
{
private:
T elem;
public:
void set (T const & t)
{ elem = t; }
T get () const
{ return elem; }
};
Now your class can be defined as
template <typename T1, typename T2>
struct Pair : wrap<T1>, wrap<T2>
{
template <typename T>
void set (T const & t)
{ wrap<T>::set(t); }
template <typename T>
T get () const
{ return wrap<T>::get(); }
};
or, if you can use C++11 and variadic templates and if you define a type traits getType to get the Nth type of a list,
template <std::size_t I, typename, typename ... Ts>
struct getType
{ using type = typename getType<I-1U, Ts...>::type; };
template <typename T, typename ... Ts>
struct getType<0U, T, Ts...>
{ using type = T; };
you can define Pair in a more flexible way as follows
template <typename ... Ts>
struct Pair : wrap<Ts>...
{
template <typename T>
void set (T const & t)
{ wrap<T>::set(t); }
template <std::size_t N, typename T>
void set (T const & t)
{ wrap<typename getType<N, Ts...>::type>::set(t); }
template <typename T>
T get () const
{ return wrap<T>::get(); }
template <std::size_t N>
typename getType<N, Ts...>::type get ()
{ return wrap<typename getType<N, Ts...>::type>::get(); }
};
Now the argument of set() can select the correct base class and the correct base element
Pair<int, long> p;
p.set(0); // set the int elem
p.set(1L); // set the long elem
otherwise, via index, you can write
p.set<0U>(3); // set the 1st (int) elem
p.set<1U>(4); // set the 2nd (long) elem
Unfortunately, the get() doesn't receive an argument, so the type have to be explicited (via type or via index)
p.get<int>(); // get the int elem value
p.get<long>(); // get the long elem value
p.get<0U>(); // get the 1st (int) elem value
p.get<1U>(); // get the 2nd (long) elem value
Obviously, this didn't work when T1 is equal to T2
The following is a (C++11) full working example
#include <iostream>
template <std::size_t I, typename, typename ... Ts>
struct getType
{ using type = typename getType<I-1U, Ts...>::type; };
template <typename T, typename ... Ts>
struct getType<0U, T, Ts...>
{ using type = T; };
template <typename T>
class wrap
{
private:
T elem;
public:
void set (T const & t)
{ elem = t; }
T get () const
{ return elem; }
};
template <typename ... Ts>
struct Pair : wrap<Ts>...
{
template <typename T>
void set (T const & t)
{ wrap<T>::set(t); }
template <std::size_t N, typename T>
void set (T const & t)
{ wrap<typename getType<N, Ts...>::type>::set(t); }
template <typename T>
T get () const
{ return wrap<T>::get(); }
template <std::size_t N>
typename getType<N, Ts...>::type get ()
{ return wrap<typename getType<N, Ts...>::type>::get(); }
};
int main()
{
//Pair<int, int> p; compilation error
Pair<int, long, long long> p;
p.set(0);
p.set(1L);
p.set(2LL);
std::cout << p.get<int>() << std::endl; // print 0
std::cout << p.get<long>() << std::endl; // print 1
std::cout << p.get<long long>() << std::endl; // print 2
p.set<0U>(3);
p.set<1U>(4);
p.set<2U>(5);
std::cout << p.get<0U>() << std::endl; // print 3
std::cout << p.get<1U>() << std::endl; // print 4
std::cout << p.get<2U>() << std::endl; // print 5
}
C++ is statically typed, so the argument given must be a template-argument instead a function-argument.
And while it will look like just one function each to the user, it's really two.
template <int i = 1> auto GetValue() -> std::enable_if_t<i == 1, T1> { return first; }
template <int i = 2> auto GetValue() -> std::enable_if_t<i == 2, T2> { return second; }
template <int i = 1> auto SetValue(T1 x) -> std::enable_if_t<i == 1> { first = x; }
template <int i = 2> auto SetValue(T2 x) -> std::enable_if_t<i == 2> { second = x; }
I use SFINAE on the return-type to remove the function from consideration unless the template-argument is right.
For this particular situation, you should definitely prefer std::pair or std::tuple.
You can simply overload SetValue() (provided T1 and T2 can be distinguished, if not you have a compile error):
void SetValue(T1 x)
{ first=x; }
void SetValue(T2 x)
{ second=x; }
Then, the compiler with find the best match for any call, i.e.
Pair<int,double> p;
p.SetValue(0); // sets p.first
p.SetValue(0.0); // sets p.second
With GetValue(), the information of which element you want to retrieve cannot be inferred from something like p.GetValue(), so you must provide it somehow. There are several options, such as
template<typename T>
std::enable_if_t<std::is_same<T,T1>,T>
GetValue() const
{ return first; }
template<typename T>
std::enable_if_t<std::is_same<T,T2>,T>
GetValue() const
{ return second; }
to be used like
auto a = p.GetValue<int>();
auto b = p.GetValue<double>();
but your initial version is good enough.
I have the following scenario: I have a struct template<typename CType, int D>
struct Point in which I want to overload the operators < and >. Here comes the catch and the point I am not sure about: I want different implementations of < and > depending on if CType is float/double or int. Right now I'm doing this using typid from typeinfo, but I feel like this is not elegant. How do I go about doing this in a clean way?
Here is one option (using non-member operators):
template<typename CType, int D>
bool operator<( Point<CType, D> const &p1, Point<CType, D> const &p2)
{
// generic logic
}
template<int D> bool operator<( Point<float, D> const &p1, Point<float, D> const &p2 )
{
// logic for float
}
It might be possible to replace float with an enable_if to make a version that works for all types of a certain type trait (e.g. have a single specialization for all floating point types).
Live demo link.
#include <iostream>
#include <type_traits>
template <typename CType, int D>
struct Point
{
template <typename T = CType>
auto operator<(int t) -> typename std::enable_if<std::is_same<T, int>::value, bool>::type
{
std::cout << "int" << std::endl;
return true;
}
template <typename T = CType>
auto operator<(float t) -> typename std::enable_if<std::is_same<T, float>::value, bool>::type
{
std::cout << "float" << std::endl;
return true;
}
};
int main()
{
Point<int, 1> pi;
Point<float, 1> pf;
pi < 5;
pf < 3.14f;
pi < 3.14f; // forced to apply operator<(int)
}
While trying to answer one question here, I found this question:
How to recursively dereference pointer (C++03)?
Adapted code from the answer is following:
template<typename T> T& dereference(T &v) { return v; }
template<typename T> const T& dereference(const T &v) { return v; }
template <typename T>
typename std::enable_if<!std::is_pointer<T>::value, T&>::type
dereference(T *v) {
return dereference(*v);
}
However, in this test it is failing to dereference pointer-to-pointer into the value type:
template <typename T>
class A
{
public:
bool compare(T a, T b){
return dereference(a) < dereference(b);
}
};
int main()
{
int u = 10;
int *v = &u;
int **w = &v;
int i = 5;
int *j = &i;
int **k = &j;
A<int> a;
A<int*> b;
A<int**> c;
std::cout << a.compare(i, u) << std::endl;
std::cout << b.compare(j, v) << std::endl;
// This fails - 5 < 10 == 0
std::cout << **k << " < " << **w << " == " << c.compare(k, w) << std::endl;
return 0;
}
Obviously, w and k are derefenced only one time, which causes operator< to be called on two pointers.
I can fix this by adding the following:
template <typename T>
typename std::enable_if<!std::is_pointer<T>::value, T&>::type
dereference(T **v) {
return dereference(*v);
}
but then it will fail for int***.
Is there any way to make this recursively without adding levels manually?
Note This is just "theoretical" question.
This is possible with the use of a custom can_dereference trait:
template <typename T>
struct can_dereference_helper {
template <typename U, typename = decltype(*std::declval<U>())>
static std::true_type test(U);
template <typename...U>
static std::false_type test(U...);
using type = decltype(test(std::declval<T>()));
};
template <typename T>
struct can_dereference :
can_dereference_helper<typename std::decay<T>::type>::type {};
and some mutually-recursive functions with a bit'o tag dispatching:
template <typename T>
auto recursive_dereference(T&& t, std::false_type) ->
decltype(std::forward<T>(t)) {
return std::forward<T>(t);
}
template <typename T>
auto recursive_dereference(T&& t) ->
decltype(recursive_dereference(std::forward<T>(t), can_dereference<T>{}));
template <typename T>
auto recursive_dereference(T&& t, std::true_type) ->
decltype(recursive_dereference(*std::forward<T>(t))) {
return recursive_dereference(*std::forward<T>(t));
}
template <typename T>
auto recursive_dereference(T&& t) ->
decltype(recursive_dereference(std::forward<T>(t), can_dereference<T>{})) {
return recursive_dereference(std::forward<T>(t), can_dereference<T>{});
}
See it work live at Coliru. This may seem like overkill compared to Kerrek's answer, but I went for a generic approach that will dereference anything that supports operator*. I'll let you decide which tool fits your problem best.
You can do it with a trait to compute the ultimate return type, here dubbed remove_all_pointers:
#include <type_traits>
template <typename T> struct remove_all_pointers
{ typedef typename std::remove_reference<T>::type type; };
template <typename T> struct remove_all_pointers<T *>
{ typedef typename std::remove_reference<T>::type type; };
template <typename T>
T & dereference(T & p)
{ return p; }
template <typename U>
typename remove_all_pointers<U>::type & dereference(U * p)
{ return dereference(*p); }
int main(int argc, char * argv[])
{
return dereference(argv);
}
You may need to add CV-variants; I'm still thinking about that.
I am a newer for C++, and my first language is Chinese, so my words with English may be unmeaningful, say sorry first.
I know there is a way to write a function with variable parameters which number or type maybe different each calling, we can use the macros of va_list,va_start and va_end. But as everyone know, it is the C style. When we use the macros, we will lose the benefit of type-safe and auto-inference, then I try do it whit C++ template. My work is followed:
#include<iostream>
#include<vector>
#include<boost/any.hpp>
struct Argument
{
typedef boost::bad_any_cast bad_cast;
template<typename Type>
Argument& operator,(const Type& v)
{
boost::any a(v);
_args.push_back(a);
return *this;
}
size_t size() const
{
return _args.size();
}
template<typename Type>
Type value(size_t n) const
{
return boost::any_cast<Type>(_args[n]);
}
template<typename Type>
const Type* piont(size_t n) const
{
return boost::any_cast<Type>(&_args[n]);
}
private:
std::vector<boost::any> _args;
};
int sum(const Argument& arg)
{
int sum=0;
for(size_t s=0; s<arg.size(); ++s)
{
sum += arg.value<int>(s);
}
return sum;
}
int main()
{
std::cout << sum((Argument(), 1, 3, 4, 5)) << std::endl;
return 0;
}
I think it's ugly, I want to there is a way to do better? Thanks, and sorry for language errors.
You can do something like this:
template <typename T>
class sum{
T value;
public:
sum ()
: value() {};
// Add one argument
sum<T>& operator<<(T const& x)
{ value += x; return *this; }
// to get funal value
operator T()
{ return value;}
// need another type that's handled differently? Sure!
sum<T>& operator<<(double const& x)
{ value += 100*int(x); return *this; }
};
#include <iostream>
int main()
{
std::cout << (sum<int>() << 5 << 1 << 1.5 << 19) << "\n";
return 0;
}
Such technique (operator overloading and stream-like function class) may solve different problems with variable arguments, not only this one. For example:
create_window() << window::caption - "Hey" << window::width - 5;
// height of the window and its other parameters are not set here and use default values
After giving it some thought, I found a way to do it using a typelist. You don't need an any type that way, and your code becomes type-safe.
It's based on building a template structure containing a head (of a known type) and a tail, which is again a typelist. I added some syntactic sugar to make it more intuitive: use like this:
// the 1 argument processing function
template< typename TArg > void processArg( const TArg& arg ) {
std::cout << "processing " << arg.value << std::endl;
}
// recursive function: processes
// the first argument, and calls itself again for
// the rest of the typelist
// (note: can be generalized to take _any_ function
template< typename TArgs >
void process( const TArgs& args ) {
processArg( args.head );
return process( args.rest );
}
template<> void process<VoidArg>( const VoidArg& arg ){}
int main() {
const char* p = "another string";
process( (arglist= 1, 1.2, "a string", p ) );
}
And here is the argument passing framework:
#include <iostream>
// wrapper to abstract away the difference between pointer types and value types.
template< typename T > struct TCont {
T value;
TCont( const T& t ):value(t){}
};
template<typename T, size_t N> struct TCont< T[N] > {
const T* value;
TCont( const T* const t ) : value( t ) { }
};
template<typename T> struct TCont<T*> {
const T* value;
TCont( const T* t ): value(t){}
};
// forward definition of type argument list
template< typename aT, typename aRest >
struct TArgList ;
// this structure is the starting point
// of the type safe variadic argument list
struct VoidArg {
template< typename A >
struct Append {
typedef TArgList< A, VoidArg > result;
};
template< typename A >
typename Append<A>::result append( const A& a ) const {
Append<A>::result ret( a, *this );
return ret;
}
//syntactic sugar
template< typename A > typename Append<A>::result operator=( const A& a ) const { return append(a); }
} const arglist;
// typelist containing an argument
// and the rest of the arguments (again a typelist)
//
template< typename aT, typename aRest >
struct TArgList {
typedef aT T;
typedef aRest Rest;
typedef TArgList< aT, aRest > Self;
TArgList( const TCont<T>& head, const Rest& rest ): head( head ), rest( rest ){}
TCont<T> head;
Rest rest;
template< typename A > struct Append {
typedef TArgList< T, typename Rest::Append<A>::result > result;
};
template< typename A >
typename Append< A >::result append( const A& a ) const {
Append< A >::result ret ( head.value, (rest.append( a ) ) );
return ret;
}
template< typename A > typename Append<A>::result operator,( const A& a ) const { return append(a); }
};