Search code examples
c++visual-c++constructormemberexplicit-instantiation

C++ explicit instantiation of template constructor of non-template class


I'm working on a C++ Fraction class that use pimpl idiom, my public header is something like (work in progress)

Fraction.h

code:

#pragma once

#include <memory>
#include <string>

class Fraction
{
public:
    Fraction();
    ~Fraction();

    template <typename N>
    Fraction(N numerator, bool normalize = true);
    template <typename N, typename D>
    Fraction(N numerator, D denominator, bool normalize = true);

    Fraction(Fraction&&);
    Fraction& operator=(Fraction&&);

    template <typename T>
    bool operator==(T const & other);
    template <typename T>
    bool operator!=(T const & other);

    std::string representation ();

private:
    class impl;
    std::unique_ptr<impl> pimpl;
};

I can have correct specialization in my cpp file using explicit instantiation for member (eg. comparison operator overload)

Fraction.cpp

partial code

template <typename T>
bool Fraction::operator==(const T& other)
{
    return pimpl->operator==(other);
}

template bool Fraction::operator==<int>(int const &);
template bool Fraction::operator==<float>(float const &);
template bool Fraction::operator==<double>(double const &);
template bool Fraction::operator==<Fraction>(Fraction const &);

But I have some VS2015 compiler error when I want do the same with the constructor:

template <typename N, typename D>
Fraction::Fraction(N num, D den, bool norm)
    : pimpl{ std::make_unique<impl<N,D>>(num, den, norm) }
{}

template Fraction::Fraction<int, int>(int, int, bool);

I get build error (in french):

C2143   erreur de syntaxe : absence de ';' avant '<' fraction.cpp [156]
C2059   erreur de syntaxe : '<'                      fraction.cpp [156] 

The fraction.cpp line 156 is:

template Fraction::Fraction<int, int>(int, int, bool);

The error in english (approx. translation) :

C2143   syntax error : absence of ';' before '<'
C2059   syntax error : '<'

I've test some variation of the explicit instantiation but I can not find a solution. I hope this is allowed by the standard?


EDIT : To answer the comment of Sam Varshavchik, the cpp class integrate the private implementation of the Fraction class in the form of:

class Fraction::impl
{
public:
    Fraction::impl()
        : _num (0)
        , _den (1)
    {}

    ...

    template <typename N, typename D>
    Fraction::impl(N numerator, D denominator, bool normalize = true)
    {
        // TODO
    }

    ...
};

Here, no need explicit specialization of the template because is a .hpp class style.


SOLUTION (Thank to Constructor for is (so evident) solution)

template <typename N, typename D>
Fraction::Fraction(N num, D den, bool norm)
    : pimpl{ std::make_unique<impl>(num, den, norm) }
{}

template Fraction::Fraction(int, int, bool);

Just:

  • Replace the impl<N,D> by impl.
  • Remove the <int, int> in the template explicit instanciation.

Solution

  • There is no syntax like this for explicit instantiation of templated contructors in C++:

    template Fraction::Fraction<int, int>(int, int, bool);
                               ^^^^^^^^^^
    

    You should use the following simple syntax instead:

    template Fraction::Fraction(int, int, bool);