模板类中的命名空间特化

时间:2018-01-19 21:59:10

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

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

#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'未在此范围内声明

2 个答案:

答案 0 :(得分:1)

  

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

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

  

有解决办法吗?

我能想象到的最好的(如果你可以大量修改你的代码)是在两个不同的类或结构中转换你的两个名称空间,所以函数变成方法(可能是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内。

答案 1 :(得分: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";
    }
};