template call seem to be unmatch - c++

I have this program with 2 template functions :
#include <iostream>
template <class T> void assign(T& t1,T& t2){
std::cout << "First method";
t1=t2;
}
template <class T> void assign(T& t1,const T& t2) {
std::cout << "Second method";
t1=t2;
}
class A
{
public:
A(int a):_a(a){};
private:
int _a;
friend A operator+(const A& l, const A& r);
};
A operator+(const A& l, const A& r) {
return A(l._a+r._a);
}
int main ()
{
A a=1;
const A b=2;
assign(a,a+b);
}
i cant understand why does the assign(a,a+b) call the second template function
, in the operator+ we are createing a new A object and call the ctor with an int parameter.
it is creating a+b as const object ?

it is creating a+b as const object ?
No, it is creating a temporary. Temporaries are binded to rvalue references. You can verify that with a 'third' function (a universal reference, in this case)
template <class T>
void assign(T& t1, T&& t2) {
std::cout << "Third method";
t1=t2;
}
As you don't have one, the compiler will pick the const reference overload. Why ?
Suppose you have
void add(int & x)
{
++x;
}
unsigned y = 0;
add(y); // create a temporary to int
std::cout << y << "\n"; // what's the value of y ?

Related

Overloading operator for default type in template

How can i overload operator in template class for every type expect- for example int and char.
Point<char> operator+ (Point<char> const& sec){
Point<char> tmp(x+2, y+3);
return tmp;
}
Point<int> operator+ (Point<int> const& sec){
Point<int> tmp(x+sec.x + 1, y+sec.y + 1);
return tmp;
}
Point<T> operator+ (Point<T> const& sec){
return Point<T>(x+sec.x, y+sec.y);
}
Something like this doesn't work. I can overload for specific types OR for T, but can't combine both.
You can explicitly specialize outside the class, like so (minimal example):
#include <iostream>
template<class T>
struct Point
{
Point operator+(Point rhs)
{
std::cout << "Generic\n";
return rhs;
}
};
template<>
Point<char> Point<char>::operator+(Point<char> rhs)
{
std::cout << "char\n";
return rhs;
}
template<>
Point<int> Point<int>::operator+(Point<int> rhs)
{
std::cout << "int\n";
return rhs;
}
int main()
{
Point<double> p;
Point<int> i;
Point<char> c;
p + p;
i + i;
c + c;
}
Live on Coliru
You can add an if statement like
if(std::is_same<T, int>::value) {...}
else if(std::is_same<T, char>::value) {...}
else {...}
Write this inside the code for Point operator+(){}.
I have never implemented this, but I think you can make it work.
I don't know if an operator can be overloaded the way you want, but you can try this.
To explicitly specialize a member you need its surrounding class template to be explicitly specialized as well. In your case you can use friends:
template <class T>
class Point {
public:
Point(T x, T y) : x(x), y(y) {}
private:
T x, y;
friend Point<char> operator+ (Point<char> const& a, Point<char> const& b);
friend Point<int> operator+ (Point<int> const& a, Point<int> const& b);
template<class T>
friend Point<T> operator+ (Point<T> const& a, Point<T> const& b);
template<class T>
friend Point<T*> operator+ (Point<T*> const& a, Point<T*> const& b);
};
Point<char> operator+ (Point<char> const& a, Point<char> const& b) {
std::cout << "overload for char" << std::endl;
return a;
}
Point<int> operator+ (Point<int> const& a, Point<int> const& b) {
std::cout << "overload for int" << std::endl;
return a;
}
template <class T>
Point<T> operator+ (Point<T> const& a, Point<T> const&) {
std::cout << "overload for other non-pointers type" << std::endl;
return a;
}
// you can even provide overload for pointers
template <class T>
Point<T*> operator+ (Point<T*> const& a, Point<T*> const&) {
std::cout << "overload for pointers" << std::endl;
return a;
}
int main() {
Point<int> p1(1,1);
p1 + p1;
Point<char> p2(1, 1);
p2 + p2;
Point<long long> p3(1, 1);
p3 + p3;
int i[2];
Point<int*> p4(i, i+1);
p4 + p4;
return 0;
}
overload for int
overload for char
overload for other non-pointer types
overload for pointers

Helper function involving std::move

codereview would not allow hypothetical code, so I am posting here instead. Given this code:
#include <string>
struct foo {
std::string a, b;
foo (const std::string& a, const std::string& b) : a(a), b(b) { }
};
template <typename T> void bar (const T&) { }
template <typename T> void bar (T&&) { }
void execute (const foo& f) {
// etc...
bar(f.a);
// etc...
bar(f.b);
// etc...
bar(f);
// etc...
}
void execute (foo&& f) {
// etc...
bar(std::move(f.a));
// etc...
bar(std::move(f.b));
// etc...
bar(std::move(f));
// etc...
}
int main() {}
I want to write execute_helper to handle both execute overloads, since they are identical except for the std::move calls. Here is what I have, and I want to know if I did it correctly. I'm unsure about using T& and T in my check_move overloads, and whether passing T by value worsens the time complexity or not.
#include <string>
#include <iostream>
struct foo {
std::string a, b;
foo (const std::string& a, const std::string& b) : a(a), b(b) { }
};
template <typename T> void bar (const T&) { }
template <typename T> void bar (T&&) { }
template <typename T>
T check_move (const foo&, T& t) { std::cout << "std::move not called.\n"; return t; }
template <typename T>
T&& check_move (foo&&, T t) { std::cout << "std::move called.\n"; return std::move(t); }
template <typename F>
void execute_helper (F&& f) {
// etc...
bar(check_move(std::forward<F>(f), f.a));
// etc...
bar(check_move(std::forward<F>(f), f.b));
// etc...
bar(check_move(std::forward<F>(f), std::forward<F>(f)));
// etc...
}
void execute (const foo& f) {
execute_helper(f);
}
void execute (foo&& f) {
execute_helper(std::forward<foo>(f));
}
// Test
foo make_foo() {
return foo("hello", "bye");
}
int main() {
foo f("hello", "bye");
execute(f);
execute(make_foo());
}
Output:
std::move not called.
std::move not called.
std::move not called.
std::move called.
std::move called.
std::move called.

Can I explicitly instantiate template member of template class without instantiating the template class?

I want to explicitly instantiate template member but without instantiation of the template class. But I am getting compiler errors, so is this possible ? Here is my code:
//mytemplate.h
template <class T>
class mytemplate
{
public:
mytemplate(T* tt)
{
mT = tt;
}
template<class B>
void print(const B& bb);
T* mT;
};
//in mytemplate.cpp
#include "mytemplate.h"
template<typename T>
template<typename B>
void mytemplate<T>:: print(const B& bb)
{
B b = bb;
}
template<typename T> void mytemplate<T>::print<float>(const float&) const;
template<typename T> void mytemplate<T>::print<int>(const int&) const;
// main.cpp
int main()
{
int d =0;
mytemplate<int> k(&d);
k.print<float>(4.0);
}
With templates, it always helps to decompose the problem into the smallest possible building block. mytemplate::print can be written in terms of a call to a template free function.
This way you can achieve the effect of partial specialisation of a member function.
A leading question here is "what should the print() method do?". Here is an example in which mytemplate<T> provides a printing policy to a free function. There is no reason of course that the policy could not be some other class which has been constructed via some other (possibly specialised) template free function.
// Policy is a concept which supports 2 methods:
// print_prefix() and print_postfix()
//
template<class Policy, class B>
void print_with_policy(const Policy& policy, const B& value) const
{
policy.print_prefix();
cout << value;
policy.print_postifx();
}
template<class T>
struct mytemplate
{
// implement in terms of a free function
template<class B> void print(const B& value) {
print_with_policy(*this, value);
}
// policy concept implementation
void print_prefix() const {
cout << "prefix-";
}
void print_postfix() const {
cout << "-postfix";
}
};
extending the example to use a separate policy class with a specialisation for strings:
template<typename B>
struct default_policy {
default_policy(const B& value) : _value(value) {}
void operator()() const {
cout << "(" << _value << ")";
}
private:
const B& _value;
};
template<typename B>
struct quoted_policy {
quoted_policy(const B& value) : _value(value) {}
void operator()() const {
cout << '"' << _value << '"';
}
private:
const B& _value;
};
template<class B>
default_policy<B> make_policy(const B& value) {
return default_policy<B>(value);
}
// overload for B being a string
quoted_policy<std::string> make_policy(const std::string& value) {
return quoted_policy<std::string>(value);
}
template<class T>
struct mytemplate
{
// implement in terms of a free function
template<class B> void print(const B& value) {
make_policy(value)();
cout << endl;
}
};
int main()
{
struct foo{};
mytemplate<foo> fooplate;
fooplate.print(int(8));
fooplate.print(std::string { "a string" });
fooplate.print("not a string");
return 0;
}
output:
(8)
"a string"
(not a string)

Reference to pointer and reference overloading

Can i call foo(const T*&) in the following situation?
#include <iostream>
template <typename T>
void foo(const T*&)
{
std::cout << "::foo(const T*&) \n";
}
template <typename T>
void foo(const T&)
{
std::cout << "::foo(const T&) \n";
}
You are confused by the fact that const T*& means a reference to a pointer to const T, rather than a const-reference to a pointer to T.
To call that version of foo, use
int main()
{
const int *iptr = 0;
foo(i);
return 0;
}
Alternatively (and probably as intended), change the function signature to T *const &, i.e. a const-reference to a pointer to T.
No, you can't with that code, because there is an implicit conversion and you will end up calling the foo(const T&) version.
If you want to separate the two behaviours use explicit:
template <typename T>
void foo(const T*&)
{
std::cout << "::foo(const T*&) \n";
}
template <typename T>
void foo(explicit const T&)
{
std::cout << "::foo(const T&) \n";
}
int main()
{
int x;
int *y=&x;
foo(x);
foo(y);
return 0;
}
This way foo(x) will call foo(const T&), whereas foo(y) will call foo(const T*&)

Friend operator behavior (const vs non-const)

I have the following C++ code:
#include <iostream>
template <class T>
void assign(T& t1, T& t2) {
std::cout << "First method" << std::endl;
t1 = t2;
}
template <class T>
void assign(T& t1, const T& t2) {
std::cout << "Second method" << std::endl;
t1 = t2;
}
class A {
public:
A(int a) : _a(a) {};
private:
int _a;
friend A operator+(const A& l, const A& r);
};
A operator+(const A& l, const A& r) {
return A(l._a + r._a);
}
int main() {
A a = 1;
const A b = 2;
assign(a, a);
assign(a, b);
assign(a, a+b);
}
The output is:
First method
Second method
Second method
The output stays the same even if I comment out the the first 2 assigns in the main function.
Can someone please explain to me why the operator+ returns a const A?
The output is the same in both Linux Debian 64bit and Windows 7 64 bit.
It doesn't return a const A at all. It returns a temporary A, which may only bind to a const reference.