2

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.
MaxC2
  • 343
  • 3
  • 10

2 Answers2

2

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);
Constructor
  • 7,273
  • 2
  • 24
  • 66
0
impl<N,D>

impl is not a template, it is a class:

class impl;

See? It's a declared class. It's not a template, and your compiler is rightfully upset that you're trying to tell it now that it's a template that must be instantiated with two template parameters, N, and D.

The intent of your code is unclear, so the correct course of action is not obvious. However, another problem is also obvious, which lies in your future: after you square away your compilation error, you will then find yourself immediately staring at a link failure, because templates can only be implemented in header files, and not in the .cpp file, as you're trying to do. At least not without some additional work.

Community
  • 1
  • 1
Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • 2
    "At least not without some additional work" Here the additional work is already in place. – n. m. could be an AI Mar 26 '17 at 15:04
  • @Sam Varshavchik - Thanks for your answer. I mention that the Fraction class is an pimpl idiom. In the cpp the private implementation is fully filled. I will add additionnal information to my question in few minutes. – MaxC2 Mar 26 '17 at 15:08