Explicit instantiation for a set of types

template instantiation vs specialization
template specialization
extern template
template instantiation c++
c++ template
c++ template class inheritance
calling function with template
template declaration

In my code usually I have to write a function that takes a "Path-like" type, that is, something that I can convert to boost::filesystem::path, for example

  • QString
  • std::string
  • const char *
  • etc...

in A.hpp

struct A
{
  template <typename PathLike> 
  void myFunction(PathLike path);
};

in A.cpp

template <typename PathLike> 
void A::myFunction(PathLike path)
{
   boost::filesystem::Path p = convertToBoostPath(path);
   //do something...
}

//Explicit instantiations needed 
template void A::myFunction(string);  
template void A::myFunction(QString);
template void A::myFunction(char const *);
//....

The problem is that if I want to do the same thing in a different function B, I need to add the explicit instantiations all over again. Maybe I'm taking a wrong approach.

Instead of writing a template function that takes any PathLike and also does the real work, write a template function that takes any PathLike, converts it to boost::filesystem::Path as shown, then calls a non-template function (whose definition can be in the .cpp) which will do the real work.

In A.hpp:

class A
{
public:
  template <typename PathLike> 
  void myFunction(PathLike path);

private:
  void myFunctionImpl(boost::filesystem::Path path);
};


template <typename PathLike> 
void A::myFunction(PathLike path)
{
  myFunctionImpl(convertToBoostPath(path));
}

In A.cpp:

void A::myFunctionImpl(boost::filesystem::Path path)
{
  // do something...
}

This has the added benefit that misuse of the interface results in compiler errors, not linker errors.

Explicit template instantiation - when is it used?, You can use explicit instantiation to create an instantiation of a templated class uninstantiated template definitions are not put into object (.obj) files. You can explicitly instantiate function templates by using a specific type� An explicit instantiation definition creates and declares a concrete class, function, or variable from a template, without using it just yet. An explicit instantiation can be referenced from other translation units. This can be used to avoid defining a template in a header file, if it will only be instantiated with a finite set of arguments.

How about create a class PathLike and use it:

class PathLike
{
public:
    explicit PathLike(const QString& path) : mPath(convertToBoostPath(path)) {}
    explicit PathLike(const std::string& path) : mPath(convertToBoostPath(path)) {}
    explicit PathLike(const char* path) : mPath(convertToBoostPath(path)) {}
    PathLike(const boost::filesystem::path& path) : mPath(path) {}

    const boost::filesystem::path& get() const { return mPath;}
    operator const boost::filesystem::path&() const { return mPath;}
private:
    boost::filesystem::path mPath;
};

(I mark other constructor explicit to promote filesystem::path, but up to you to add/remove explicit).

And then:

struct A
{
    void myFunction(PathLike path)
    {
       boost::filesystem::path p = path;
       //do something...
    }
};

Explicit Instantiation, This can be used to avoid defining a template in a header file, if it will only be instantiated with a finite set of arguments. For example: // print_string.h template� An explicit instantiation definition of a template is in the same namespace where you define the template. Access checking rules do not apply to the arguments in the explicit instantiation definitions. Template arguments in an explicit instantiation definition can be private types or objects.

One way to explicitly instantiate a function template for a pack of types is to take the address of each function instantiation. E.g.:

template<class... Ts>
void instantiate_myFunction() {
    auto f = [](auto&&) { return 1; };
    auto initializer_list = { f(&A::myFunction<Ts>)...  };
    static_cast<void>(initializer_list);
}

int main() {
    instantiate_myFunction<std::string, char const*>();
}

C++, A class template by itself is not a type, or an object, or any other entity. An explicit instantiation definition forces instantiation of the class, struct, no effect if an explicit specialization appeared before for the same set of template arguments . Explicit instantiation has no effect if an explicit specialization appeared before for the same set of template arguments.. Only the declaration is required to be visible when explicitly instantiating a function template, a variable template, a member function or static data member of a class template, or a member function template.

Class template, There are two forms of explicit instantiation: an explicit instantiation definition is inline ([namespace.def]), any namespace from its enclosing namespace set. However, we can add specialized template support through explicit template instantiation which will add the symbols needed to link (properly) against the library for use. Take the following revision of the Example.cpp:

13.9.2 Explicit instantiation [temp.explicit], can explicitly tell the compiler when it should generate a definition from a template. This is called explicit instantiation. Explicit instantiation includes two forms:� Explicit Instantiation. 11/04/2016; 2 minutes to read +2; In this article. You can use explicit instantiation to create an instantiation of a templated class or function without actually using it in your code.

Explicit instantiation (C++ only), Once the template classes are instantiated you can instantiate objects of that type (for example, fs and is.) A good programming practice is using typedef while� This is called implicit instantiation. The compiler does not need to generate the specialization for nonclass, noninline entities when an explicit instantiation declaration is present. If the compiler must instantiate a class template specialization and the template is declared, you must also define the template.

Comments
  • Why not just define the function in a header file? You can use SFINAE to constrain the type if you need to.
  • You have to write a different instantiate_myFunction for every function template you want to do this for, correct? As far as I know the only thing you can do with a function template is instantiate it (as opposed to class templates, which can be passed as template template parameters), sadly...
  • @MaxLanghof That is true, using Path class is the right solution, IMO.