【问题标题】:pimpl idiom and template class friendpimpl 成语和模板类朋友
【发布时间】:2009-10-16 17:59:36
【问题描述】:

我正在尝试使用 pimpl 习惯用法来隐藏一些蹩脚的模板代码,但我不能让 body 类的派生类访问句柄类。我从 MSVC 9 sp1 收到错误 C2248。这是一些复制错误的代码:

//
// interface.hpp
//
namespace internal{
    template<class T>
    class specific_body;
}

class interface
{
    struct body;
    body *pbody_;
    interface(body *pbody);

    template<class T>
    friend class internal::specific_body;

public:

    ~interface();

    interface(const interface &rhs);

    bool test() const;

    static interface create( bool value );
};

//
// interface.cpp
//
struct interface::body
{
    virtual ~body(){}

    virtual bool test() const = 0;

    virtual interface::body *clone() const = 0;
};

class true_struct {};
class false_struct {};

namespace internal {

template< class T>
class specific_body : public interface::body
{ // C2248
public:

    specific_body(){}

    virtual bool test() const;

    virtual interface::body *clone() const
    {
        return new specific_body();
    }
};

bool specific_body<true_struct>::test() const
{
    return true;
}

bool specific_body<false_struct>::test() const
{
    return false;
}

} //namespace internal

interface::interface(body *pbody) : pbody_(pbody) {}

interface::interface(const interface &rhs) : pbody_(rhs.pbody_->clone()) {}

interface::~interface() { delete pbody_; }

bool interface::test() const
{
    return pbody_->test();
}

interface interface::create(bool value )
{
    if ( value )
    {
        return interface(new internal::specific_body<true_struct>());
    }
    else
    {
        return interface(new internal::specific_body<false_struct>());
    }
}

//
// main.cpp
//
// #include "interface.hpp"
//

int _tmain(int argc, _TCHAR* argv[])
{
    interface object( interface::create(true));

    if ( object.test() )
    {
        // blah
    }
    else
    {
    }
    return 0;
}

任何帮助将不胜感激,如果我的问题不是很明显,我正试图向 interface 的用户隐藏 interface::bodyspecific_body 实现。

【问题讨论】:

    标签: c++ templates friend pimpl-idiom


    【解决方案1】:

    需要在模板测试方法的显式实例化中添加模板

    template<> // add this line
    bool specific_body<true_struct>::test() const
    {
        return true;
    }
    

    【讨论】:

    • 是的,我忘记在我的示例中将这些行添加到测试方法的专业化中,但它们没有帮助。感谢您的意见。
    • 检查您的示例中是否缺少某些内容。修复它使用 gcc 4.4.1 编译的那一行并且工作正常。
    • 嗯,它们似乎与微软的编译器没有什么不同,所以看起来像是一个编译器一致性问题。感谢您的意见。
    【解决方案2】:

    你没有资格specific_body。试试

    template<class T>
    friend class internal::specific_body;
    

    作为你的朋友声明。

    【讨论】:

    • 感谢您的建议,但无济于事
    • 出于兴趣,如果您删除命名空间internal 即仅将specific_body 放入全局命名空间,这一切都会开始工作吗?
    【解决方案3】:

    尝试使用 typename 可能吗?我想我在 Sutter 中读到 typename 可以进入未知范围内的 class,而 class 不会。

    【讨论】:

    • 我想你把它放在朋友之后或之前
    【解决方案4】:

    除了 Troubadour 提到的不合格的 specific_body 之外,您对 true_struct 和 false_struct 的 specific_body::test 的专业化尝试似乎不正确。你必须专攻全班。

    为了解决这个问题,我只需在公共部分声明body。将 specific_body 声明为 interface::body 的朋友也无济于事。

    【讨论】:

    • 我不确定为什么在这种情况下完全专门化 specific_body 类会很重要。我在我的代码中声明body public 的一个案例有帮助,但我还有另一个案例specfic_body 也需要访问interface 的私​​有构造函数;所以我想解决朋友访问问题,或者重组代码以达到我可以从 body 类中固有的相同目的。
    • 完全专业化无法使其符合 C++ 标准。如果您在该部分没有收到任何错误,您的编译器可能会支持它作为扩展,我不知道。但 GCC 拒绝它。只是说...
    • 您认为这里不合规的具体内容是什么?只专门化模板类的成员函数而不专门化整个类在 C++ 中是完全合法的。通俗的讲,类模板的每个成员函数本身就是一个独立的模板,可以独立特化。这是一个很少使用的功能,但它就在那里。 14.7.3/16 包含此类专业化的示例。
    • 他试图在没有模板关键字的情况下对其进行专门化
    • 哦,是的,我错过了。我确实需要带有template&lt;&gt; 位的典型显式专业化语法。但仍然没有必要“专门化全班”。
    【解决方案5】:

    好吧,我可以通过在界面中将body 设为公共声明来“解决”这个问题。这解决了specific_body 声明期间的 C2248 错误。我还让body 成为interface 类的朋友,并向body 结构添加了一个方法:

    static interface create( body *pbody )
    {
        return interface(pbody);
    }
    

    如果specific_body 的实例之间存在嵌套关系,则specific_body 可以创建interface

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-21
      • 2011-03-18
      • 1970-01-01
      • 1970-01-01
      • 2016-10-29
      • 2011-10-14
      • 2017-08-08
      • 1970-01-01
      相关资源
      最近更新 更多