Moment of evaluation of a template differs for subclass??

Hi,

I have the following code:

1
2
3
template<typename T1, typename T2>
struct common_type_metafunction : std::common_type<T1,T2>
{};


And this is used in:

1
2
typedef typename apply<common_type_metafunction<_1,_2>, float, long>::type common_type;
typedef typename apply<std::common_type<_1, _2>, float, long>::type direct_common_type;


where _1 and _2 are boost placeholders. The first typedef works just fine; the second returns


no conversion from 'boost::mpl::_2' to 'boost::mpl::_1


So, the second is trying to evaluate std::common_type before the "call" to apply, whereas the first is postponing such evaluation even though it inherits from std::common_type.

We can ignore apply's definition because the issue here is why std::common_type<_1,_2> is instantiated before apply is called, whereas common_type_metafunction<_1,_2> is evaluated later.

For clarity though, here is the definition of apply:

1
2
3
template <typename F, typename... Args>
struct apply : lambda<F>::type::template apply<Args...>
{};


And the primary and partially specialized templates of lambda:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// In the general case, F is either a metafunction class or a placeholder expression
// We will deal with placeholder expressions in partially specialized templates of this one
// In this particular case, we assume F is a metafunction class (i.e. it contains a nested 
// metafunction called apply - a metafunction is a template or class if it does not have 
// non-type parameters and if it also returns a type called type -- i.e. nested) 
	template <typename F>
	struct lambda
	{
	typedef F type;

	template< typename... Args>
	struct apply
	{
	typedef typename F::template apply<Args...>::type type;
	};
};

template<template<typename> class F>
struct lambda<F<_1>>
{
	typedef lambda<F<_1>> type;

	template<typename... Args>
	struct apply
	{
	typedef typename F<Args...>::type type;
	};
};


template<template<typename, typename> class F>
struct lambda<F<_1,_2>>
{
typedef lambda<F<_1,_2>> type;

template<typename... Args>
struct apply
{
    typedef typename F<Args...>::type type;
	};
};


Why is the instantiation of the superclass of common_type_metafunction not done before the call to apply?

Regards,
Juan
In apply<common_type_metafunction<_1,_2>, float, long>,
std::common_type<T1,T2> is a dependent base class; it is not part of the current instantiation.

For details, see 'Current instantiation' in: http://en.cppreference.com/w/cpp/language/dependent_name
Thanks JLBorges! My confusion was that when creating an object of a subclass, the superclasses are constructed first, so I thought the same would happen when using class templates .... I am still a bit confused on this topic, if you care to elaborate a bit: why is the superclass not constructed (read: instantiated) before the subclass?

Best regards,
Juan Dent
> why is the superclass not constructed (read: instantiated) before the subclass?

Objects are constructed, not classes. The instantiation in this context refers to the instantiation of the template; not the construction of an object. To make the distinction clear: function templates are instatiated.

Templates are subject to two-phase name look up. The first phase is when the template definition is seen, before any template instantiation takes place; the second phase is when an actual instantiation of the template takes place. Names that are deduced to refer to the current instantiation of a class template are looked up during phase one; names that are not part of the current instantiation are looked up during phase two.

For a simplified explanation see: 'Why am I getting errors when my template-derived-class uses a nested type it inherits from its template-base-class?' here: https://isocpp.org/wiki/faq/templates
Thanks!!!

Juan
Topic archived. No new replies allowed.