单例元编程

Meta programming with singleton

本文关键字:编程 单例元      更新时间:2023-10-16

我想根据单例类的枚举值在两个不同的代码路径之间进行选择。 单例类继承自"CSingleton"类型,其中 T 是新类的类型。

enum class Paths
{
    PATH_ONE = 0,
    PATH_TWO,    
}
template<Paths pathValue>
class Foo : public CSingleton<Foo>
{
public:
    Foo()
    {
        if(pathValue == Paths::PATH_ONE)
             myValue = 11;
        else if(pathValue == Paths::PATH_TWO)
             myValue = 22;
    }
    int myValue;
};

然后,当使用对象时,我可以执行以下操作:

assert(11 == Foo<Paths::PATH_ONE>::Instance().myValue);

明确地说,Instance() 将创建对象。

我想做的事情有名字吗? Boost 或 C++11 是否有一部分可以帮助我?

谢谢!

您实际上是在尝试做出运行时决策并在编译时做出决策。 对于这个简单的示例,只需将枚举值强制转换为int

即可
myValue = static_cast<int>(pathValue);

但更好的方法可能是创建一个接受参数的构造函数:

Foo(const Paths& path)
{
    if(path == Paths::PATH_ONE)
    {
         // do something
    }
    else if(path == Paths::PATH_TWO)
    {
         // do something else
    }
}

在这种情况下,您的类不再需要成为模板:

class Foo : public SomeParent { ... };

另一种解决方案是专门化值的模板,但您需要 2 个类声明。

解决此类问题的一种常用元编程方法(无论是否具有单例类!)如下:

enum Selections
{
    PATH_ONE ,
    PATH_TWO ,
};
class ImplBase : public ImplBase
{
    // Declare an interface and common implementation bits
}
class ImplBaseOne : public ImplBase
{
    // Implement details for PATH_ONE
};
class ImplBaseTwo
{
    // Implement details for PATH_TWO
};

template<Selections Choice>
struct Selector
{
     typedef void Result; // This should result in a compiler error for 
                          // invalid/unknown specializations
};
template<>
struct Selector<PATH_ONE>
{
     typedef ImplBaseOne Result;
};
template<>
struct Selector<PATH_ONE>
{
     typedef ImplBaseOne Result;
};
template<>
struct Selector<PATH_TWO>
{
     typedef ImplBaseTwo Result;
};

template<Selections Choice>
class ExposedClass : public Selector<Choice>::Result
{
    // ...
}

您有几种方法可以在编译时执行所需的操作,这些方法将转换为模板专用化:

1. 只为价值

template<Paths> struct MyValue;
template<> struct MyValue<Paths::PATH_ONE> { static constexpr int value = 11; };
template<> struct MyValue<Paths::PATH_TWO> { static constexpr int value = 22; };

所以你有:

Foo() { myValue = MyValue<pathValue>::value; }

2. 对于功能

您可以创建多个参数化的函数/方法

template<Paths> void MyAssignVariable(int& var);
template<> void MyAssignVariable<Paths::PATH_ONE>(int& var) { var = 11; };
template<> void MyAssignVariable<Paths::PATH_TWO>(int& var) { var = 22; };

所以你有:

Foo() { MyAssignVariable<pathValue>(myValue); }

由于功能无法实现部分专业化,因此首选以下内容:

template<Paths> struct PathSpecialization;
template<> struct PathSpecialization<Paths::PATH_ONE> {
    static void MyAssignVariable(int& variable) { variable = 11; };
    // You may add other methods here.
};
template<> struct PathSpecialization<Paths::PATH_TWO> {
    static void MyAssignVariable(int& variable) { variable = 22; };
    // You may add other methods here.
};

所以你有:

Foo() { PathSpecialization<pathValue>::MyAssignVariable(myValue); }