I'm new to C++ and I'm trying to use template but I got problems.
What I'm trying to do is: try to calculate square of a number using template, and the number may be basic data types like int, float, as well as complex numbers. I also implemented a complex class using template, and the codes are as follows:
template <typename T>
class Complex {
public:
T real_;
T img_;
Complex(T real, T img) : real_(real), img_(img) { }
};
template <typename T>
T square(T num) {
return num * num;
}
template <>
Complex<typename T> square(Complex<typename T> num) {
T temp_real = num.real_*num.real_ - num.img_*num.img_;
T temp_img = 2 * num.img_ * num.real_;
return Complex(temp_real, temp_img);
}
I tried to use template specialization to deal with the special case, but it gave me error:
using ‘typename’ outside of template
and the error happens on the template specialization method. Please point out my mistakes. Thanks.
It appears that you're trying to partially specialize function templates, which isn't actually possible in C++. What you want instead is to simply overload the function like this:
template<typename T>
T square(T num) // Overload #1
{
return num * num;
}
template<typename T>
Complex<T> square(Complex<T> num) // Overload #2
{
T temp_real = num.real_*num.real_ - num.img_*num.img_;
T temp_img = 2 * num.img_ * num.real_;
return Complex<T>(temp_real, temp_img);
}
Informally, the compiler will always pick overload #2 over overload #1 when the argument is of type Complex<T> because it's a better match.
Another way to make this work is to overload the multiplication operator for the Complex<> class using the definition of multiplication for complex numbers. This has the advantage of being more general and you can extend this idea to other operators.
template <typename T>
class Complex
{
public:
T real_;
T img_;
Complex(T real, T img) : real_(real), img_(img) {}
Complex operator*(Complex rhs) // overloaded the multiplication operator
{
return Complex(real_*rhs.real_ - img_*rhs.img_,
img_*rhs.real_ + real_*rhs.img_);
}
};
// No overload needed. This will work for numeric types and Complex<>.
template<typename T>
T square(T num)
{
return num * num;
}
Since you are new to C++, I highly recommend that you pick up a good introductory C++ book. Templates and operator overloading aren't exactly beginner's topics.
Related
I'm making a template class for fractions, the numerator and denominator can be of type int, float or double. When overloading the arithmetic or relational operators it gives errors when I try to add two class, say class A and class B
in the header file "fraction.h"
#include<iostream>
using namespace std;
template <class T>
class fraction
{
friend ostream& operator<< <T>(ostream&, const fraction<T>&);
public:
fraction();
fraction<T>(T, T);
friend fraction<T> operator+(const fraction<T>&, const fraction<T>&);
private:
T numerator;
T denominator;
};
template <class T>
fraction<T>::fraction()
{
numerator = 0;
denominator = 1;
}
template <class T>
fraction<T>::fraction(T num, T denom)
{
numerator = num;
denominator = denom;
}
template <class T>
ostream& operator<<(ostream& osObject, const fraction<T>& frac)
{
osObject << frac.numerator << "/" << frac.denominator;
return osObject;
}
template <class T>
fraction<T> operator+(const fraction<T>& fraction1, const fraction<T>& fraction2)
{
fraction<T> temp;
temp.numerator = fraction1.numerator * fraction2.denominator + fraction1.denominator * fraction2.numerator;
temp.denominator = fraction1.denominator * fraction2.denominator;
return temp;
}
and in cpp file
#include"fraction.h"
int main()
{
fraction<int> num1(5,6);
fraction<double> num2(5.1,6.1);
fraction<double> num3();
cout << num1+num2;
}
I expect it to display 10.1/12.1 but instead, it gives Compiler Error C2678 that says binary '+': no operator found which takes a lefthand operand of type 'fraction' (or there is no acceptable conversion). I spend much time trying to solve this problem, and what I understand now that because num1 and num2 are of different types they cannot be added and because the return of '+' operator is not specified to be of any type. How can I solve this problem?
Your overloaded operator+ function takes two const fraction<T>& arguments. The problem is that the two arguments you use are of different type, the T template for each are different.
To begin solving it you need to use different types for each argument, which means two template arguments. You also need to have a common type for the returned faction object.
Something like
template <typename U, typename V>
fraction<std::common_type_t<U, V>> operator+(const fraction<U>& fraction1, const fraction<V>& fraction2)
{
fraction<std::common_type_t<U, V>> temp;
// ...
return temp;
}
Note that I use different template argument names for both of them. That's because it should be easier to copy-paste for the friend declaration (that must also be updated to match the new function), and you can't shadow a template argument (that is, because the class have an template argument names T the friend function declaration can't have it as well).
Recently I am learning the template function in C++. I am wondering if there is any simple way for me to do the following thing.
For example, I have defined a template function in C++ as follow:
template <typename T, float t_p>
void func_a(T* input, T* output):
{
output = input / t_p;
}
Now, I want to define another template function based on this template function for f_p = 4.0. I know I may be able to do the following thing:
template <typename T>
void func_b(T* input, T* output):
{
func_a<T,4.0>(input, output);
}
but this code looks very heavy. Especially when I have many input variables. I am wondering if there is any way that I can do to be similar as follows
template <typename, T>
func_b = func_a<T , 4.0>;
If so, it will be very helpful
You can't do it with functions, but you can do it with functors. S.M. noted that you can't use float as a template non-type parameter, so let's replace it with int. I also suppose that you want to operate on values, not on pointers (either dereference pointers, or use references).
template<int t_p>
struct func_a
{
template<typename T>
void operator()(const T& input, T& output) const
{
output = input / t_p;
}
};
using func_b = func_a<4>;
using func_c = func_a<5>;
Now you can use these functors in the following way:
void foo()
{
int a = 100;
int b;
func_a<2>()(a, b);
func_b()(a, b);
func_c()(a, b);
}
Note that you need extra empty parentheses to create a functor.
If you want to use float you can do something like this:
struct func_a
{
func_a(float p) : p(p) { }
template<typename T>
void operator()(const T& input, T& output) const
{
output = input / p;
}
private:
const float p;
};
void foo()
{
const auto func_b = func_a(4);
const auto func_c = func_a(5);
float a = 100;
float b;
func_a(2)(a, b);
func_b(a, b);
func_c(a, b);
}
Maybe a little Off Topic but I give you a useful, I hope, little suggestion: switch the order of your template parameters.
I mean: write func_a() as follows (I use int for t_p because, as pointed by S.M., a float value can't a valid template parameter)
template <int t_p, typename T>
void func_a(T* input, T* output):
{ output = input / t_p; }
The point is that T can be deduced from the function arguments (input and output) where t_p can't be deduced so must be explicated.
If the order is T first and t_p second, you must explicate also T, so (by example) in func_b() you must write
func_a<T,4>(input, output);
If the order is t_p first and T second, you must explicate only t_p and you can let the compiler deduce the T type; so you can simply write
func_a<4>(input, output);
In this case is a little improvement but, in other circumstances, can be useful.
In Haskell, typeclasses allow for you to elegantly overload functions based on return type. It is trivial to replicate this in C++ for cases where both the arguments and the return type are overloaded, using templates (example A):
template <typename In, typename Out> Out f(In value);
template <typename T> int f<T, int>(T value) {
...
}
Which corresponds to Haskell's:
class F a b where
f :: a -> b
You can even overload just the return type on most functions (example B):
template <typename Out> Out f(SomeClass const &value);
template <> inline int f(SomeClass const &value) {
return value.asInt();
}
template <> inline float f(SomClass const &value) {
return value.asFloat();
}
Which corresponds to something like:
class F a where
f :: SomeData -> a
But what I would like to be able to do is modify this last example to overload on higher-order types, namely templated structs in C++. That is, I'd like to be able to write a specialization akin to the following Haskell:
data Foo a = Foo a
instance F (Foo a) where
f someData = Foo $ ...
How would one go about writing a template with this functionality (is it even possible)?
For reference, I'm intending to use this to write template functions for Lua/C++ bridge. The idea is to bridge between Lua and C++ functions by having an overloaded function interpretValue that automatically pushes or converts from the Lua stack. For simple types that have a direct built-in Lua representation, this is easy enough using code such as example B.
For more complicated types, I'm also writing a template <typename T> struct Data to handle memory management for objects (bridging between Lua's GC and a C++ side refcount), and I was hoping to be able to overload interpretValue so that it can automatically wrap a userdata pointer into a Data<T>. I tried using the following, but clang gave a "function call is ambiguous" error:
template <typename U> inline U &interpretValue(lua_State *state, int index) {
return Data<U>::storedValueFromLuaStack(state, index);
}
template <typename U> inline Data<U> interpretValue(lua_State *state, int index) {
return Data<U>::fromLuaStack(state, index);
}
Thanks!
Well, you can write one function:
template <class U>
interpretValueReturnType<U> interpretValue(lua_State *state, int index)
{
return interpretValueReturnType<U>(state, index);
}
Then, you need to write this return type with casting operators, so, you get what you want:
template <class U>
class interpretValueReturnType
{
public:
interpretValueReturnType(lua_State *state, int index) : state(state), index(index) {}
operator U& () &&
{
return Data<U>::storedValueFromLuaStack(state, index);
}
operator Data<U> () &&
{
return Data<U>::fromLuaStack(state, index);
}
private:
lua_State *state;
int index;
};
See ideone:
int main() {
lua_State *state;
int& a = interpretValue<int>(state, 1);
Data<int> b = interpretValue<int>(state, 1);
}
This funny && at the end of operators declarations are for making a little hard to store result of this function and use it later - like here:
auto c = interpretValue<float>(state, 1);
float& d = c; // not compile
One'd need to use std::move because && means that function can be used only for rvalue references:
auto c = interpretValue<float>(state, 1);
float& d = std::move(c);
I have following example:
struct Wrapper
{
virtual ~Wrapper()
{
}
template <typename U>
WrapperT<U> * clone()
{
return new WrapperT<U>(value); //will not work, because value is not known here
}
};
template <typename T>
struct WrapperT : Wrapper
{
explicit WrapperT(T v)
{
value = v;
}
T value;
};
and I want something like this:
Wrapper *t = new WrapperT<int>(1);
WrapperT<double> *t2 = t->clone<double>();
I know virtual templates are not available. Any ideas?
A possible approach is defining a visitor pattern, but the cost of implementing the visitor might be large if you want to support many different wrapped types (i.e. if it is not just a small subset).
Another problem you would get is that the conversions would be (have to be) dynamically dispatched, so they can fail at runtime and you would have to provide mechanisms to detect that and act on that then (exceptions come to mind). Nothing horrible...
The solution I propose is using a "neutral type" to make dynamically (as David Rodríguez - dribeas noted) the type conversion.
Advantage:
The solution is generic: you don't need to so any special thing when using a new type.
As drawbacks
Not good for performance.
Requires the insertion and extraction stream operators to be defined.
The code:
struct Wrapper
{
// get the "neutral type" value
virtual string getValue() const = 0;
template <typename U> Wrapper* clone() const;
};
template <typename T>
struct WrapperT: Wrapper
{
explicit WrapperT(T v): value(v)
{
}
virtual string getValue() const
{
// use streams to conversion to neutral value, but
// other better method would be suitable
ostringstream strm;
strm << value;
return strm.str();
}
T value;
};
template <typename U> Wrapper* Wrapper::clone() const {
U value;
istringstream strm(getValue());
strm >> value;
return new WrapperT<U>(value);
}
EDIT:
For a better performance solution, if only using numeric type, we can change string by a long double as "neutral type":
template <typename T>
double long WrapperT<T>::getValue() const
{
return value;
}
template <typename U> Wrapper* Wrapper::clone() const {
return new WrapperT<U>(getValue());
}
Do we want to avoid integral to floating point conversions when using only integral type? In that case, the solution will be a bit more complex:
create two getValue() virtual functions, one for integral and other one for floating point,
in clone() function select the desired getValue() function depending on U template parameter type (target type).
Here, the context of polymorphic is expecting 'Derived' from 'Base&.
Given
class P { };
class Q : public P { };
auto operator + (const P& p, int x) -> DYNAMIC_DECLTYPE(P) {
DYNAMIC_DECLTYPE(P) p2(p);
p2.func(x);
return p2;
}
Is there a way to have DYNAMIC_DECLTYPE working? I want to use this form instead of
template <typename T> T operator + (const T& t, int x)
or have a potentially long list of
if (!strcmp(typeid(p).name(), typeid(derived()).name()) { ... }
because the latter cannot be used to restrict T to P or subclasses thereof (prove me wrong, if possible).
What you are trying to do is in every sense of the word a template pattern: You have an unbounded family of return types with matching function argument types. This should simply be a straight template.
If you want to restrict the permissible types, you should add some typetrait magic. Perhaps like this:
#include <type_traits>
template <typename T>
typename std::enable_if<std::is_base_of<P, T>::value, T>::type
operator+(T const & t, int x)
{
T s(t);
s.func(x);
return s;
}
(If func returns a reference, you can shortcut this to return T(t).func(x);.)