Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to explicitly instantiate a template for all members of MPL vector in C++?

Tags:

Consider the following header file:

// Foo.h
class Foo {
    public: 
        template <typename T>
        void read(T& value);
};

I want to explicitly instantiate the Foo::read member function template in a source file for all types included in a boost::mpl::vector:

// Foo.cc
#include <boost/mpl/vector.hpp>
#include <boost/mpl/begin_end.hpp>
#include "Foo.h"

template <typename T>
void Foo::read(T& value) { /* do something */ }

typedef boost::mpl::vector<int, long, float> types;

// template Foo::read<int  >(int&);
// template Foo::read<long >(long&);
// template Foo::read<float>(float&);

// instantiate automatically ???

Is it possible? Thanks in advance, Daniel.

EDIT

I found some solution - it seems that assigning a pointer to Foo::read<T> in the constructor of a struct, of which variable is then declared, cause instantiation:

// intermezzo
template <typename T> struct Bar {
    Bar<T>() {
        void (Foo::*funPtr)(T&) = &Foo::read<T>;
    }
};

static Bar<int  > bar1;
static Bar<long > bar2;
static Bar<float> bar3;

So then the process can be automatized as follows:

// Foo.cc continued
template <typename B, typename E>
struct my_for_each {
    my_for_each<B, E>() {
        typedef typename B::type T;      // vector member
        typedef void (Foo::*FunPtr)(T&); // pointer to Foo member function
        FunPtr funPtr = &Foo::read<T>;   // cause instantiation?
    }

    my_for_each<typename boost::mpl::next<B>::type, E> next;
};

template<typename E>
struct my_for_each<E, E> {};

static my_for_each< boost::mpl::begin<types>::type,
                    boost::mpl::end<types>::type > first;

But I don't know if this solution is portable and standard-conformant? (Works with Intel and GNU compilers.)

like image 870
Daniel Langr Avatar asked Apr 19 '11 11:04

Daniel Langr


1 Answers

I've had the same requirement not long ago, and had good results with a simple function template instantiation:

template <class... T>
void forceInstantiation(typedef boost::mpl::vector<T...>*) {

    using ex = int[];
    (void)ex{(void(&Foo::read<T>), 0)..., 0};

    // C++17
    // (void)((void(&Foo::read<T>), ...));
}

template void forceInstantiation(types*);
like image 61
Quentin Avatar answered Sep 19 '22 00:09

Quentin