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:
impl<N,D>
by impl
.<int, int>
in the template explicit instanciation.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);