【问题标题】:namespace specialization in template class模板类中的命名空间特化
【发布时间】:2018-01-19 21:59:10
【问题描述】:

我有两个不同的命名空间,它们以两种不同的方式实现相同的方法和类。我正在编写一个使用这些方法和类来做某事的类,我想知道是否有一种方法可以在没有部分特化的情况下声明命名空间,如下所示:

#include <string>
#include <iostream>

namespace one
{
int test()
{
    return 1;
}
}

namespace two
{
int test()
{
    return 2;
}
}

enum names : int
{
    first = 1,
    second = 2
};

template <names>
struct base_class;

template <>
struct base_class<names::first>
{
    using namespace ::one;
};

template <>
struct base_class<names::second>
{
    using namespace ::two;
};

template <names ns>
struct delcare_namespace : public base_class<ns>
{
    delcare_namespace()
    {
        std::cout << test() << "\n";
    }
};

对于上面的代码,我得到了

test' 没有在这个范围内声明

【问题讨论】:

  • using namespace 不允许在类范围内。
  • @Jaa-c。我知道,这段代码只是我需要的演示,有解决方法吗?
  • 这看起来像an XY problem。你想用这样的解决方案解决什么真正的问题?
  • @Someprogrammerdude:这实际上是我想要解决的一个真正的问题,我有一个为系统套接字提供接口的类,该套接字的另外三个实现在不同的命名空间中提供了类似的方法,如果我能做这样的事情,我就能将所有的类简化为一个并维护一个代码
  • @apramc:我能想到的最好的方法是像static constexpr auto test = &amp;one::test; 这样向继承的类添加一个成员,而不是在delcare_namespace 中调用this-&gt;test()。但是没有办法在类范围内以某种方式使用命名空间或声明命名空间别名。

标签: c++ c++11 templates template-meta-programming template-specialization


【解决方案1】:

using namespace 不允许在类范围内,命名空间别名也不允许。我不认为你可以做一个会以某种方式注入命名空间的专业化。

不完全相同,但如果可以选择在特化中从该命名空间声明您需要的所有函数,则可以将函数指针作为该特化的成员:

template <names>
struct base_class;

template <>
struct base_class<names::first>
{
    static constexpr auto test = &one::test;
};

template <>
struct base_class<names::second>
{
    static constexpr auto test = &two::test;
};

template <names ns>
struct delcare_namespace : public base_class<ns>
{
    delcare_namespace()
    {
        std::cout << this->test() << "\n";
    }
};

【讨论】:

    【解决方案2】:

    我想知道是否有办法声明命名空间

    不幸的是,我认为在类/结构中并继承它是不可能的。

    有解决办法吗?

    我能想象的最好的(如果你可以大量修改你的代码)是在两个不同的类或结构中转换你的两个命名空间,所以函数变成了方法(可能是static 方法)

    struct baseOne  // former namespace one
     {
       static int test ()
        { return 1; }
     };
    
    struct baseTwo // former namespace two
     {
       static int test ()
        { return 2; }
     };
    

    因此您可以将基类(以前的命名空间)作为模板参数传递并从中继承

    template <typename B>
    struct foo : public B
     {
       foo ()
        { std::cout << B::test() << "\n"; }
     };
    

    以下是一个完整的工作示例

    #include <string>
    #include <iostream>
    
    struct baseOne  // former namespace one
     {
       static int test ()
        { return 1; }
     };
    
    struct baseTwo // former namespace two
     {
       static int test ()
        { return 2; }
     };
    
    template <typename B>
    struct foo : public B
     {
       foo ()
        { std::cout << B::test() << "\n"; }
     };
    
    int main ()
     {
       foo<baseOne> f1; // print 1
       foo<baseTwo> f2; // print 2
     }
    

    如果在方法名之前使用B::让你很烦,你可以将基础结构中的static方法转换为普通方法或添加指令为

    using B::test;
    

    foo 内。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-17
      • 1970-01-01
      • 1970-01-01
      • 2015-08-04
      • 1970-01-01
      • 2018-06-24
      相关资源
      最近更新 更多