是否可以通过模板方法在模板类上定义typedef?

时间:2016-11-08 20:13:26

标签: c++ templates typedef

假设我有一个类似的模板类:

template <typename T>
struct TypeInformation {
    static int s_someArbitraryData;
}
template <typename T> TypeInformation<T>::s_someArbitraryData = 0;

然后,稍后我可以做这样的事情:

SomeFunction() {
    SetUpData<int>(); // Populates s_someArbitraryData for int.
}

仅通过调用SetUpData,我就为给定的类型设置了一个s_someArbitraryData副本。如果可能的话,我想做的是做类似的事情,但设置一种映射类型的方法。像这样的东西,目前不起作用:

template <typename T>
struct MyTypeMap {}

// ...

SomeFunction() {
    SetUpTypemap<int, float>(); // Creates a typedef on MyTypeMap<int>
    MyTypeMap<int>::type myFloatValue = 1.0f; // A float value
}

我可以通过这样的方式完成这个right now

template <>
struct MyTypeMap<int> {
    typedef float type;
}

但这对我的情况有一些恼人的弊端。我怀疑我想要的是不可能的,但如果有一些深层模板魔法,我也不会感到惊讶,我不知道可以解决这个问题。

1 个答案:

答案 0 :(得分:0)

这可能与您所寻找的内容相距甚远:

#include<type_traits>

template<typename T>
struct tag { using type = T; };

template<typename...>
struct MapPart;

template<typename T, typename U, typename... O>
struct MapPart<T, U, O...>: MapPart<O...> {
    using MapPart<O...>::get;
    static constexpr tag<U> get(tag<T>) { return {}; }
};

template<>
struct MapPart<> {
    static constexpr void get();
};

template<typename... T>
struct Map: MapPart<T...> {
    template<typename U>
    using type = typename decltype(Map<T...>::template get<U>())::type;

    template<typename U>
    static constexpr auto get() {
        return MapPart<T...>::get(tag<U>{});
    }
};

int main() {
    using MyTypeMap = Map<int, float>;
    static_assert(std::is_same<MyTypeMap::type<int>, float>::value, "!");
    MyTypeMap::type<int> myFloatValue = 1.0f;
}

最终语法略有不同。你有这个:

MyTypeMap::type<int>

而不是:

MyTypeMap<int>::type

无论如何,我认为这是可以接受的。

类型MyTypeMap仅在using声明的范围内可见。我认为这是原始SetUpTypemap<int, float>函数的意图:仅在函数int内设置floatSomeFunction之间的绑定。

通过使用这种方法,您可以同时设置多个关系 举个例子:

using MyTypeMap = Map<int, float, float, int>;

// ....

MyTypeMap::type<int> myFloatValue = 1.0f;
MyTypeMap::type<float> myIntValue = 1;

另请注意,类型的第一个关系集是最强的 换句话说,如果你这样做:

using MyTypeMap = Map<int, float, int, char>;

MyTypeMap::type<int>类型将为float,它会隐藏intchar之间的关系。

不是一个完美的解决方案,但可能是解决您问题的有效解决方案。