【问题标题】:Specializing a function for a private class?为私有类专门化一个函数?
【发布时间】:2013-08-20 21:22:26
【问题描述】:

有没有办法为私有类专门化一个函数(例如,std::swap)?

例如,当我测试这个时:

#include <algorithm>

class Outer
{
    struct Inner
    {
        int a;
        void swap(Inner &other)
        {
            using std::swap;
            swap(this->a, other.a);
        }
    };
public:
    static void test();
};

namespace std
{
    template<> void swap<Outer::Inner>(Outer::Inner &a, Outer::Inner &b)
    { a.swap(b); }
}
void Outer::test()
{
    using std::swap;
    Inner a, b;
    swap(a, b);
}
int main()
{
    Outer::test();
    return 0;
}

我明白了:

Test.cpp:20:47: error: 'Inner' is a private member of 'Outer'
    template<> void swap<Outer::Inner>(Outer::Inner &a, Outer::Inner &b)
                                              ^
Test.cpp:5:12: note: implicitly declared private here
    struct Inner
           ^
Test.cpp:20:64: error: 'Inner' is a private member of 'Outer'
    template<> void swap<Outer::Inner>(Outer::Inner &a, Outer::Inner &b)
                                                               ^
Test.cpp:5:12: note: implicitly declared private here
    struct Inner
           ^
Test.cpp:20:33: error: 'Inner' is a private member of 'Outer'
    template<> void swap<Outer::Inner>(Outer::Inner &a, Outer::Inner &b)
                                ^
Test.cpp:5:12: note: implicitly declared private here
    struct Inner

(我确实意识到声明可以通过 ADL 找到的朋友 swap 可以避免 swap 的这个问题,但这与我的问题无关。swap 只是一个示例。)

【问题讨论】:

  • friend void swap(Inner, Inner) 放入Outer
  • @TemplateRex:这不会专门化std::swap,它只是一个名为swap 的非成员函数。
  • 你不能专门化一个不可见的类。由于struct 被声明为具有私有访问权限,因此只有Outer 可以看到它。因此,您不能创建可以看到它的非外部成员函数 - 阻止您专门化它。
  • @ZacHowland:例如,有没有办法将其声明为friend?我觉得应该有,但我找不到任何有效的语法......而且我不明白为什么它不应该是可能的。
  • @Mehrdad 下一次尝试:朋友声明侧外。查看更新的答案。

标签: c++ private friend template-specialization specialization


【解决方案1】:

您可以在Outer 内添加std::swap&lt;Inner&gt;(Inner&amp;, Inner&amp;)friend 声明

#include <algorithm>

class Outer
{
    struct Inner
    {
        int a;
        void swap(Inner &other)
        {
            using std::swap;
            swap(this->a, other.a);
        }
    };

    friend void std::swap<Inner>(Inner&, Inner&) noexcept;
public:
    static void test();
};

namespace std
{
    template<> void swap<Outer::Inner>(Outer::Inner &a, Outer::Inner &b) noexcept
    { a.swap(b); }
}

void Outer::test()
{
    using std::swap;
    Inner a, b;
    swap(a, b);
}

int main()
{
    Outer::test();
    return 0;
}

Live Example

【讨论】:

  • 顺便说一句,noexcept 是关闭更多编译器错误所必需的(因为主模板也有)
【解决方案2】:

不要扩展 std 命名空间。

如果您想为Inner 创建一个交换函数,请将其设为Outer 中的私有函数

#include <algorithm>

class Outer
{
    struct Inner
    {
        int a;
        void swap(Inner &other)
        {
            std::swap(this->a, other.a);
        }
    };

    static void swap(Inner& a, Inner& b);

public:
    static void test();
};

void Outer::test()
{
    Inner a, b;
    swap(a, b);
}

void Outer::swap(Inner& a, Inner& b)
{
    a.swap(b);
}

int main()
{
    Outer::test();
    return 0;
}

【讨论】:

  • -1 你没有回答这个问题。假设stdfooswapbar,现在我不再扩展std。那我该如何专攻bar
  • 我确实回答了。您不能为看不到私有访问 struct 的函数创建专用方法。因此,要获得您想要的功能,请在 Outer 中创建一个名为 swap 的私​​有函数,该函数调用您的 Inner::swap 方法。由于InnerOuter 之外不可见,因此不需要专门的外部函数。
  • 嗯,你的评论回答了它,但你的帖子没有。我不同意“没有必要”,但如果不可能,那就回答我的问题......
  • 另外,对于这个特定的问题,请参阅:stackoverflow.com/questions/8617305/…
  • 是的,我知道这在 C++11 中大部分是不必要的,但我仍然与 C++03 兼容。
猜你喜欢
  • 2019-11-30
  • 1970-01-01
  • 2015-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多