1

我正在开发一个使用 pimpl idiom 的 C++ Fraction 类,我的公共标头类似于(正在进行中)

Fraction.h

代码:

#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;
};

我可以使用成员的显式实例化在我的 cpp 文件中进行正确的专业化(例如,比较运算符重载)

Fraction.cpp

部分代码

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 &);

但是当我想对构造函数做同样的事情时,我遇到了一些 VS2015 编译器错误:

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);

我收到构建错误(法语):

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

fraction.cpp 第 156 行是:

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

英文错误(大约翻译):

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

我已经测试了显式实例化的一些变体,但我找不到解决方案。我希望这是标准允许的吗?


编辑:为了回答 Sam Varshavchik 的评论,cpp 类以以下形式集成了 Fraction 类的私有实现:

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
    }

    ...
};

在这里,不需要模板的显式特化,因为它是一个 .hpp 类样式。


解决方案(感谢Constructor是(如此明显的)解决方案)

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);

只是:

  • 替换impl<N,D>by impl
  • 删除<int, int>模板中的显式实例化。
4

2 回答 2

1

对于 C++ 中模板化构造函数的显式实例化,没有这样的语法:

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

您应该改用以下简单语法:

template Fraction::Fraction(int, int, bool);
于 2017-03-26T16:02:04.277 回答
0
impl<N,D>

impl不是模板,它是一个类:

class impl;

看?这是一个声明的类。它不是模板,你的编译器理所当然地感到不安,因为你现在试图告诉它它是一个必须用两个模板参数实例化的模板N, 和D

您的代码的意图尚不清楚,因此正确的操作过程并不明显。但是,另一个问题也很明显,那就是你的未来:在你解决编译错误后,你会发现自己立即盯着链接失败,因为模板只能在头文件中实现,而不能在.cpp文件中实现,正如你正在尝试做的那样。至少不是没有一些额外的工作。

于 2017-03-26T14:58:01.627 回答