创建从一种类型到另一种类型的别名 我在C++中编写了一些DI容器,我很好奇,如果在现代C++中,可以从一个类型到另一个类型创建别名。 我基本上想做的是能够通过它的别名接口调用实现构造函数。像这样: di::Register<Interface, Impl>(); di::Resolve<Interface>(); // -> Impl should be resolved di::Register(); di::Resolve();//->Impl应该得到解决

创建从一种类型到另一种类型的别名 我在C++中编写了一些DI容器,我很好奇,如果在现代C++中,可以从一个类型到另一个类型创建别名。 我基本上想做的是能够通过它的别名接口调用实现构造函数。像这样: di::Register<Interface, Impl>(); di::Resolve<Interface>(); // -> Impl should be resolved di::Register(); di::Resolve();//->Impl应该得到解决,c++,c++11,metaprogramming,C++,C++11,Metaprogramming,问题是,到目前为止,我还没有找到在编译时访问alias接口和Impl的方法。我可以用RTTI来做这件事,但我真的不想用它。有可能吗 问题是,到目前为止,我还没有找到在编译时访问alias接口和Impl的方法。我可以用RTTI来做这件事,但我真的不想用它。有可能吗 假设我正确理解了你的目标,你可以使用一个技巧来实现这一点。它不会像你在那里看到的那样好看: 这个把戏是马特·卡拉布雷斯干的,他在书中这样描述 据我所知,这个技巧是符合标准的,但是你必须非常小心——如果你确实在一些头文件中开始注册,然后

问题是,到目前为止,我还没有找到在编译时访问alias接口和Impl的方法。我可以用RTTI来做这件事,但我真的不想用它。有可能吗

问题是,到目前为止,我还没有找到在编译时访问alias接口和Impl的方法。我可以用RTTI来做这件事,但我真的不想用它。有可能吗

假设我正确理解了你的目标,你可以使用一个技巧来实现这一点。它不会像你在那里看到的那样好看:

这个把戏是马特·卡拉布雷斯干的,他在书中这样描述

据我所知,这个技巧是符合标准的,但是你必须非常小心——如果你确实在一些头文件中开始注册,然后在一些CPP文件中继续注册,如果你不小心的话,你可能会导致ODR违规

我想你会得到一些宏观的

REGISTER_PAIR( interface, impl );
然后你会有一些类型别名,例如

get_registered_impl_t<interface>
get\u registered\u impl\t
解析为
impl


在本例中,它们显示了如何创建随时间累积的类型列表。在您的情况下,它将是一个类型级别“对”的列表,您可以通过线性扫描进行搜索。您可以尝试使用一种奇特的编译时映射数据结构,但在大多数情况下,它毫无意义,因为线性扫描速度足够快,而且,您可以创建的列表的长度受编译器的最大模板实例化深度的限制,通常是100或200左右。如果您需要更大的列表,可以使用一些技巧,但我不在此详述。

通过查看代码的界面,如果您有一个全局状态(我不积极推荐),您应该避免:

using type_id_t = void(*)();
template<typename> void type_id() {}

struct di {
    using create_function_t = void*(*)();
    static std::unordered_map<type_id_t, create_function_t> types;

    template<typename I, typename T>
    static void Register() {
        types.emplace(type_id<I>, []{
            return static_cast<void*>(
                static_cast<I*>(new T)
            );
        });
    }

    template<typename I>
    static std::unique_ptr<I> Resolve() {
        return std::unique_ptr<I>{static_cast<I*>(types[type_id<I>]())};
    }
};
使用类型_id_t=void(*)();
模板无效类型_id(){}
结构di{
使用create_函数_t=void*(*)();
静态std::无序的_映射类型;
模板
静态无效寄存器(){
类型.位置(类型id,[]{
返回静态输出(
静态铸件(新T型)
);
});
}
模板
静态std::unique_ptr Resolve(){
返回std::unique_ptr{static_cast(类型[type_id]())};
}
};

您可能会喜欢阅读类似的内容。实际上,我在使用
kgr::Default
@GuillaumeRacicot时做了一些非常类似的事情。是的,但我不想在这种情况下使用继承,我认为它会使接口非常庞大。@s0nicYouth继承是我的实现选择。但是如果你稍微修改一下代码,你也可以用语句做同样的事情。是的,你是对的。我将在这里使用全局状态。虽然我的目标是实现一些非常接近dagger2的东西。感谢您的snipet,但正如我提到的,我正在寻找一种在编译时实现它的方法。类似于使用I=T。但无论如何,您的解决方案是RTTI的好替代品。我不建议使用全局状态。特别是对于DI。这段代码在没有任何全局状态的情况下使用起来非常简单。只需删除所有静态关键字,瞧,我明白了。但对我来说,全球状况不是问题所在。我的问题的主要目标是找到在编译时绑定类型的方法。不幸的是,即使我删除了全局状态,您的解决方案也不能做到这一点。