可以生成从字符串到类类型的查找

时间:2015-05-23 20:01:20

标签: c++ design-patterns

我想做以下事情: 我有一个模板类,有3种类型:

file:util.h

template <typename T1, typename T2, typename T3>
  DoSomething(string p1, string p2, string p3){
    // Do something. 
  }

main.cc导入了很多类,我需要遍历很多类类型。

file:main.cc

# include "util.h"
# include "type1.h"
# include "type2.h"
# include "type3.h"
# include "type4.h"
REGISTER("process1", type1::Type1);
REGISTER("process2", type2::Type2);
REGISTER("process3", type3::Type3);
REGISTER("process4", type4::Type4);

int n = NumRegisteredStrings() // returns 4 (for process1...process4)
for (i=0; i < n-2; i++) {
    p1 = FetchStringName(i); 
    p2 = FetchStringName(i+1);
    p3 = FetchStringName(i+2);
    // When i=0, p1, p2, p3 = (process1, process2, process3) and 
    // t1, t2, t3 are (Type1, Type2, Type3)
    // When i=1, p1, p2, p3 = (process2, process3, process4) and
    // t1, t2, t3 are (Type2, Type3, Type4)                      
    const auto t1 = FetchTypeFromRegistry(p1); 
    const auto t2 = FetchTypeFromRegistry(p2); 
    const auto t3 = FetchTypeFromRegistry(p3);

    DoSomething<t1, t2, t3>(p1, p2, p3);
}

手工创建太多的调用很痛苦。我对注册管理机构的评价很少,但我们并不知道它们是如何运作的。有一个很好的资源,有一个例子,看看我是否可以用它来完成这项工作?

否则,我最终会编写以下代码(容易出错):

main () {
DoSomething<Type1, Type2, Type3>("process1", "process2", "process3");
DoSomething<Type2, Type3, Type4>("process2", "process3", "process4");
}

我真正想要的是

void Helper(string string1, string string2, string string3) {
  DoSomething<GetRegisteredType(string1),
              GetRegisteredype(string2),
              GetRegisteredType(string3)>(string1, string2, string3);
}
   main () {
    // I should not have to specify the type names here.
    // They should be automatically inferred in calling the templated function.
    Helper("process1", "process2", "process3");
    Helper("process2", "process3", "process4");
   }

2 个答案:

答案 0 :(得分:0)

您的问题非常模糊,但看起来您正在尝试最小化您必须维护的类似代码的数量。这可以使用预处理程序指令完成。

例如,如果您必须执行以下操作:

a0(arg_0);
b0(arg_0);
a1(arg_1);
b1(arg_1);
a2(arg_2);
b2(arg_2);

您可以像这样定义预处理器指令:

#define AB(n) \
  a##n(arg_##n); \
  b##n(arg_##n);

现在第一个代码段相当于

AB(0)
AB(1)
AB(2)

如果你想迭代多个数字,你可以使用可变参数或Boost.Preprocessor

例如,使用BOOST_PP_REPEAT

#include <boost/preprocessor/repetition/repeat.hpp>

#define AB(z, n, text) \
  a##n(arg_##n); \
  b##n(arg_##n);

BOOST_PP_REPEAT(3, AB, nil)

答案 1 :(得分:0)

如果我理解你正确,你想要注册名称或typeid的类型,以便以后能够对它进行一些操作。

此代码在visual studio 2013中经过测试,工作正常。

#include <iostream>
#include <map>

using namespace std;

class Interface
{
public:
    virtual std::string Greetings() = 0;
};

class Type1:public Interface
{
public:
    Type1()
    {
    }

    ~Type1()
    {
    }

    std::string Greetings()
    {
        return "Hello from Type1";
    }
private:

};

namespace SomeNamespace
{
    class Type2:public Interface
    {
    public:
        Type2()
        {
        }

        ~Type2()
        {
        }

        std::string Greetings()
        {
            return "Hello from SomeNamespace::Type2";
        }
    private:

    };
}

typedef Interface* (*Delegate)(void);//signature of the fucntion pointer

std::map< std::string, Delegate > objectFactories;

template<class Type> Interface* GetInstance()
{
    return new Type();
}

int _tmain(int argc, _TCHAR* argv[])
{
    objectFactories["Type1"] = GetInstance < Type1 > ;
    objectFactories["SomeNamespace::Type2"] = GetInstance < SomeNamespace::Type2 > ;

    for (auto&item : objectFactories)
    {
        cout << "Greetings from '" << item.first.c_str() << "' is \"" << item.second()->Greetings().c_str() << "\"" << endl;
    }

    cin.get();
    return 0;
}

输出

Greetings from 'SomeNamespace::Type2' is "Hello from SomeNamespace::Type2"
Greetings from 'Type1' is "Hello from Type1"