Asked  6 Months ago    Answers:  5   Viewed   25 times

After few weeks break, I'm trying to expand and extend my knowlege of templates with the book Templates – The Complete Guide by David Vandevoorde and Nicolai M. Josuttis, and what I'm trying to understand at this moment is explicit instantiation of templates.

I don't actually have a problem with the mechanism as such, but I can't imagine a situation in which I would like or want to use this feature. If anyone can explain that to me I will be more than grateful.

 Answers

16

Directly copied from https://docs.microsoft.com/en-us/cpp/cpp/explicit-instantiation:

You can use explicit instantiation to create an instantiation of a templated class or function without actually using it in your code. Because this is useful when you are creating library (.lib) files that use templates for distribution, uninstantiated template definitions are not put into object (.obj) files.

(For instance, libstdc++ contains the explicit instantiation of std::basic_string<char,char_traits<char>,allocator<char> > (which is std::string) so every time you use functions of std::string, the same function code doesn't need to be copied to objects. The compiler only need to refer (link) those to libstdc++.)

Tuesday, June 1, 2021
 
devo
answered 6 Months ago
16

GCC according to C++11 cannot deduce the type for either first two calls to bar. It warns because it implements an extension to C++11.

The Standard says that when a function argument in a call to a function template is a { ... } and the parameter is not initializer_list<X> (optionally a reference parameter), that then the parameter's type cannot be deduced by the {...}. If the parameter is such a initializer_list<X>, then the elements of the initializer list are deduced independently by comparing against X, and each of the deductions of the elements have to match.

template<typename T>
void f(initializer_list<T>);

int main() {
  f({1, 2}); // OK
  f({1, {2}}); // OK
  f({{1}, {2}}); // NOT OK
  f({1, 2.0}); // NOT OK
}

In this example, the first is OK, and the second is OK too because the first element yields type int, and the second element compares {2} against T - this deduction cannot yield a constradiction since it doesn't deduce anything, hence eventually the second call takes T as int. The third cannot deduce T by any element, hence is NOT OK. The last call yields contradicting deductions for two elements.

One way to make this work is to use such a type as parameter type

template <class T> void bar(std::initializer_list<std::initializer_list<T>> x) {
  // ...
}

I should note that doing std::initializer_list<U>({...}) is dangerous - better remove those (...) around the braces. In your case it happens to work by accident, but consider

std::initializer_list<int> v({1, 2, 3});
// oops, now 'v' contains dangling pointers - the backing data array is dead!

The reason is that ({1, 2, 3}) calls the copy/move constructor of initializer_list<int> passing it a temporary initializer_list<int> associated with the {1, 2, 3}. That temporary object will then be destroyed and die when the initialization is finished. When that temporary object that is associated with the list dies, the backing-up array holding the data will be destroyed too (if the move is elided, it will live as long as "v"; that's bad, since it would not even behave bad guaranteedly!). By omitting the parens, v is directly associated with the list, and the backing array data is destroyed only when v is destroyed.

Sunday, July 18, 2021
 
ramdemon
answered 5 Months ago
42

The RequestContext initializer will run any context processors listed in the settings file, but it also takes a list of additional processors to run. Any general purpose context processors can be put in settings.py and more specific ones can be added to the RequestContext on a case-by-case basis.

Leave RequestContext out altogether to not run any context processors.

# want context processors listed in settings.py as well as some more specific ones
return render_to_response('template.html', {'foo':'bar'}, context_instance=RequestContext(request, processors = extra_processors))

# want only context processors listed in settings.py
return render_to_response('template.html', {'foo':'bar'}, context_instance=RequestContext(request))

# no context processors
return render_to_response('template.html', {'foo':'bar'})
Sunday, August 1, 2021
 
MKM
answered 4 Months ago
MKM
11

No difference at all. I prefer first one (mostly), but that is my personal taste. The language doesn't make any difference between them.

For template parameters, the keywords typename and class are equivalent. §14.1.2 says:

There is no semantic difference between class and typename in a template-parameter.


If both are same,then why do we have them both if one is enough?

Stan Lippman explains this in his article:

Why C++ Supports both Class and Typename for Type Parameters?

Friday, August 6, 2021
 
borrible
answered 4 Months ago
54

I don't think you can do this with variadic templates, but you can do it with the preprocessor.

I see two options. One would be to use Boost.Preprocessor:

// Definitions:
#define ARGUMENTS (T0)(T1)(T2)(T3)(Tx)

#define INSTANTIATE(maUnused, maTemplate, maType) 
  template class maTemplate<maType>;


// Usage:
BOOST_PP_SEQ_FOR_EACH(INSTANTIATE, Impl, ARGUMENTS)

BOOST_PP_SEQ_FOR_EACH(INSTANTIATE, Impl2, ARGUMENTS)

Another option would be to use the X macro trick:

x.hpp

X(T0)
X(T1)
X(T2)
X(T3)
X(Tx)

#undef X

using_file.cpp

#define X(maType) template class Impl<maType>;
#include "x.hpp"

#define X(maType) template class Impl2<maType>;
#include "x.hpp"
Thursday, August 12, 2021
 
Tak
answered 4 Months ago
Tak
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share