【问题标题】:c++ Runtime template parameter identificationc++运行时模板参数识别
【发布时间】:2014-07-26 20:52:08
【问题描述】:

我正在编写一个游戏,我使用了一个 ResourceHolder 模板类,它提供了加载和访问资源(纹理、音乐、字体...)的功能。它适用于 Texture 或 Font 类,因为它们具有相同的加载接口(它们的函数称为“loadFromFile”),但 Music 类的工作方式有点不同,它有一个“openFromFile”函数(我使用一个名为 SFML 的库) .

template <typename Resource, typename Identifier>
void ResourceHolder<Resource, Identifier>::load(Identifier id, 
                                                const std::string & fileName)
{
    std::unique_ptr<Resource> resource(new Resource());

    resource->loadFromFile(fileName);
}

我尝试了 if-else 方法:

if (typeid(id).name() == "Resources::MusicType")
    resource->openFromFile(fileName);
else
    resource->loadFromFile(fileName);

但是编译器在编译模板的 Texture 版本时会抛出一个错误,因为它没有 openFromFile 方法。我还考虑过将该函数作为第三个模板参数传递,但我想知道是否有更好的解决方案。谢谢。

【问题讨论】:

  • 您可以为Resources::MusicType 创建部分特化。
  • check-for-a-functions-existence相关,如果测试是基于方法的存在而不是类型。
  • 谢谢大家,我选择了模板专业化方式,因为在这种情况下它似乎是最直接的方式。

标签: c++ templates


【解决方案1】:

Template Specialization 是你的朋友。

基本上你可以为特定类型创建一个专门的函数:

template <typename Resource>
void ResourceHolder<Resource, MusicType>::load(...)

我不确定这是不是正确的方法,因为我不确定ResourceIdentifier 之间的区别以及您如何使用它们。

【讨论】:

    【解决方案2】:

    具有以下 type_traits:

    #include <cstdint>
    
    #define DEFINE_HAS_SIGNATURE(traitsName, funcName, signature)               \
        template <typename U>                                                   \
        class traitsName                                                        \
        {                                                                       \
        private:                                                                \
            template<typename T, T> struct helper;                              \
            template<typename T>                                                \
            static std::uint8_t check(helper<signature, &funcName>*);           \
            template<typename T> static std::uint16_t check(...);               \
        public:                                                                 \
            static                                                              \
            constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t); \
        }
    
    DEFINE_HAS_SIGNATURE(has_loadFromFile, T::loadFromFile, void (T::*)(const std::string&));
    

    你可以使用标签调度:

    template <typename Resource, typename Identifier>
    class ResourceHolder
    {
        struct load_tag{};
        struct open_tag{};
    public:
        void load(Identifier id,
                  const std::string& fileName)
        {
            load(id, fileName,
                 typename std::conditional<has_loadFromFile<Resource>::value,
                     load_tag, open_tag>::type{});
        }
    
    private:
        void load(Identifier id,
                  const std::string& fileName,
                  load_tag)
        {
            std::unique_ptr<Resource> resource(new Resource());
    
            resource->loadFromFile(fileName);
        }
        void load(Identifier id,
                  const std::string& fileName,
                  open_tag)
        {
            std::unique_ptr<Resource> resource(new Resource());
    
            resource->openFromFile(fileName);
        }
    
    };
    

    或 SFINAE:

    template <typename Resource, typename Identifier>
    class ResourceHolder
    {
    public:
        template <typename T = Resource>
        typename std::enable_if<has_loadFromFile<T>::value>::type
        load(Identifier id,
             const std::string& fileName)
        {
            std::unique_ptr<Resource> resource(new Resource());
    
            resource->loadFromFile(fileName);
        }
        template <typename T = Resource>
        typename std::enable_if<!has_loadFromFile<T>::value>::type
        load(Identifier id,
             const std::string& fileName)
        {
            std::unique_ptr<Resource> resource(new Resource());
    
            resource->openFromFile(fileName);
        }
    
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-12
      • 2010-10-11
      • 2019-12-12
      • 2011-11-14
      • 2011-05-23
      • 2014-04-25
      • 2016-11-18
      相关资源
      最近更新 更多