Perfect Forwarding: std::forward and std::move


Based on the source code below, here is the forwarding result:
Input parameter                    Forwarded to
int intNonConst:                     (int&)
const int intConst:                  (const int&)
6(just a literal):                        (int&&) or if (int&&) doesn’t exist, to (const int& i)
std::move(intNonConst)):      (int&&)
int IntTemp():                          (int&&)
Why std::forward: otherwise, when a rvalue is passed, e.g. 6, std::move or IntTemp(), it gets forwarded to &, instead of &&.
Why std::move: so that a lvalue such as intNonConst can be treated as rvalue, and therefore be forwarded to &&
Summary: std::forward is to deal with rvalue forwarding, and it does not affect rvalue reference, regardless of constness

int IntTemp() { return 0; }
void TestForwardingFuncCalled(const int& i)
{
	cout << "const &" << endl;
};
void TestForwardingFuncCalled(int& i)
{
	cout << "&" << endl;
};
void TestForwardingFuncCalled(int&& i)
{
	cout << "&& " << endl;
};

template  void TestForwardingTemplateFunc(T&& t)
{
	cout << "Results with std::forward" << endl;
	TestForwardingFuncCalled(std::forward(t));
	cout << "Results without std::forward" << endl;
	TestForwardingFuncCalled(t);
}

void TestForwarding()
{
	int intNonConst = 2;
	const int intConst = 3;
	TestForwardingTemplateFunc(intNonConst); //with std::forward: (int&)", without std::forward: same
	TestForwardingTemplateFunc(intConst); //with std::forward: (const int&)", without std::forward: same
	TestForwardingTemplateFunc(6); //with std::forward: (int&&) or if (int&&) doesn't exist, to (const int& i), without std::forward: (int&)
	TestForwardingTemplateFunc(std::move(intNonConst)); //with std::forward: (int&&), without std::forward: (int&)
	TestForwardingTemplateFunc(IntTemp());  //with std::forward: (int&&), without std::forward: (int&)
}
void main()
{
	TestForwarding();
}

 

Advertisements

typename vs class (Visual Studio 2010)


Under what circumstances does NOT ‘class’ replace ‘typename’?

struct C
{
class CC{};
typedef CC CC2;
};
template<class T> //using 'class' is fine
struct D
{
typename T::CC2 c1; //'typename' cannot be prelaced by 'class'
class T::CC c2; //using 'class' is fine
//T::CC c3; //error: 'T::CC' : dependent name is not a type
//class T::CC2 c4; //error C2242: typedef name cannot follow class/struct/union
//T::CC2 c5; //error: 'T::CC2' : dependent name is not a type
};
D<C> a;

Summary: if the subtype if not typedef-ed, class can do the job of typename.
Otherwise, it has to be typename.

A minimum iterator template that works with ostream_iterator


This iterator works with std::ostream_iterator to get the container’s content printed to cout.
It’s minimum because it stops working if I take one more element out.
Minimum snippets is best to show how things work under the hood.

template <class T> class CMyContainer
{
public:
	enum {MAX = 2}; //only hold two elements
protected:
    T maData[MAX];
public:
    CMyContainer<T>(const T& t1, const T& t2)
	{
		maData[0] = t1; maData[1] = t2; //pre-initialized to only 2 element
	}
    class iterator;
    iterator begin()
	{
		return iterator(0, this);
	}
    iterator end()
	{
		return iterator(MAX, this);
	}
};
template <class T> class CMyContainer<T>::iterator
{
    CMyContainer<T> * mpContainer;
    int miIndex;
public:
	typedef std::forward_iterator_tag iterator_category;
	typedef void value_type;
	typedef void difference_type;
	typedef void distance_type;
	typedef void pointer;
	typedef void reference;
    iterator () {}
    iterator (int iIndex, CMyContainer<T> * c): miIndex(iIndex), mpContainer(c) {}
    bool operator==(const iterator & z)
	{
		return miIndex == z.miIndex;
	}
    bool operator!=(const iterator & z)
	{
		return !operator==(z);
	}
    void operator++()
	{
		++ miIndex;
    }
    T& operator*()
	{
		return mpContainer->maData[miIndex];
	}
};

void TestCustomIterator()
{
	CMyContainer<int> b(1, 2);
	CMyContainer<int>::iterator it;
	ostream_iterator<int> o(cout, " ");
	copy(b.begin(), b.end(), o); //this line prints 1 2 (content of b)
}

std::forward vs static_cast


For perfect forwarding, I am still trying to give an use case in which std::forward<T> works but static_cast<T&&> doesn’t.
It was suggested just to use static_cast<T&&> to implement std::forward<T>, but it had problems.
I’d like to pin point the problem with the simplest snippet.
It’s very much appreciated if you have a solution to share with me.