在另一个命名空间内创建静态模板类的“实例”

问题描述 投票:0回答:1

有一个静态模板类,用于枚举到字符串的转换,反之亦然。

下面的代码在 enum.cpp 模块中生成一组不可读的模板相关编译错误:

//helpers.hpp
namespace helpers {
template<typename T>
class Convert {
public:    
    static std::string toStr(T) { return m_convert[T]; }
    static T fromStr(std::string) { return m_convert.begin()->first; }
private:
    static std::map<T, std::string> m_convert;
};
}
...

//enum.hpp
namespace A::B::C::D {
enum class ImportantEnum {
    item1,
    item2,
};
}
...

//enum.cpp
#include "helpers.hpp"
#include "enum.hpp"

namespace A::B::C::D {
template<>
std::map<ImportantEnum, std::string> helpers::Convert<ImportantEnum>::m_convert = {
    {item1, "item1"},
    {item2, "item2"},
}
}
...

//enum_lover.cpp
#include "helpers.hpp"
#include "enum.hpp"

namespace A::B::C::D {
void do() {
    std::string s = helpers::Convert<ImportantEnum>::toStr();
}
}

如果我在 enum.cpp 中使用以下代码,它就会开始编译并工作:

//enum.cpp
#include "helpers.hpp"
#include "enum.hpp"

namespace A::B::C::D {
template<>
std::map<A::B::C::D::ImportantEnum, std::string> helpers::Convert<A::B::C::D::ImportantEnum>::m_convert = {
    {A::B::C::D::item1, "item1"},
    {A::B::C::D::item2, "item2"},
}
}

有没有办法更方便的实现这种helper?

c++ templates static namespaces
1个回答
0
投票

这应该就是您正在寻找的。

我没有看到需要类模板。在下面的代码中,

Convert
是一个常规类。如果需要的话,应该可以用它制作一个模板。

在实践中,我会考虑合并枚举和辅助文件。我在这里将它们分开,以便符合您原来的问题。

// enum.hpp
#ifndef ENUM_H
#define ENUM_H
namespace A::B::C::D {
    enum class ImportantEnum {
        item1 = 42,
        item2,
    };
}
#endif
// end file: enum.hpp
// helpers.hpp
#ifndef HELPERS_H
#define HELPERS_H
#include <map>
#include <string>
#include "enum.hpp"
namespace A::B::C::D
{
    class Convert {
    public:
        static std::string toStr(ImportantEnum const e);
        static ImportantEnum fromStr(std::string const& s);
    private:
        static std::map<ImportantEnum, std::string> m_enum_lookup;
        static std::map<std::string, ImportantEnum> m_string_lookup;
    };
}
#endif
// end file: helpers.hpp
// helpers.cpp
#include <map>
#include <string>
#include "enum.hpp"
#include "helpers.hpp"
namespace A::B::C::D
{
    std::string Convert::toStr(ImportantEnum const e) {
        return m_enum_lookup[e];
    }
    ImportantEnum Convert::fromStr(std::string const& s) {
        return m_string_lookup[s];
    }
    std::map<ImportantEnum, std::string> Convert::m_enum_lookup {
        { ImportantEnum::item1, "item1" },
        { ImportantEnum::item2, "item2" }
    };
    std::map<std::string, ImportantEnum> Convert::m_string_lookup {
        { "item1", ImportantEnum::item1 },
        { "item2", ImportantEnum::item2 }
    };
}
// end file: helpers.cpp
// main.cpp
#include <iostream>
#include "enum.hpp"
#include "helpers.hpp"
int main() {
    using A::B::C::D::ImportantEnum;
    using A::B::C::D::Convert;
    auto s1{ Convert::toStr(ImportantEnum::item1) };
    auto s2{ Convert::toStr(ImportantEnum::item2) };
    auto from1{ Convert::fromStr(s1) };
    auto from2{ Convert::fromStr(s2) };
    auto const to1{ Convert::toStr(from1) };
    auto const to2{ Convert::toStr(from2) };
    std::cout 
        << "Convert::toStr(ImportantEnum::item1) : \"" << to1 << '"'
        << "\nConvert::toStr(ImportantEnum::item2) : \"" << to2 << '"'
        << "\n\n";
    return 0;
}
// end file: main.cpp
Convert::toStr(ImportantEnum::item1) : "item1"
Convert::toStr(ImportantEnum::item2) : "item2"
© www.soinside.com 2019 - 2024. All rights reserved.