我如何 "generate" 从可变参数模板参数中为函数模板特殊化?

How can I "generate" template spezialations for a function from a variadic template argument?

我想我会先展示例子然后解释它:

#include <array>

template<typename T_, size_t size_>
struct arg
{
    using T = T_;
    static constexpr size_t size = size_;
};

template<typename... Arugments>
struct Foo
{
    template<typename Argument>
    std::array<typename Argument::T, Argument::size>& getArray() // specializations of all args in Arguments should be generated
    {
        static std::array<typename Argument::T, Argument::size> arr;
        return arr;
    }
};

int main()
{
    Foo<arg<int, 10>, arg<float, 10>, arg<float, 1>> myFoo;
    myFoo.getArray<arg<int, 10>>();
    myFoo.getArray<arg<float, 10>>(); // should return a different array than the line above
    myFoo.getArray<arg<bool, 1>>(); // should NOT work because arg<bool, 10> is was not passed to Foo
}

如果得到一个结构 arg,其中包含如何在 getArray 中构造 arr 的信息。 args 列表被传递给 Foo。现在我希望为 Arguments 中的每个 arg 生成 getArray 的模板特化。如果没有为特定的 arg 生成专业化,我希望发生某种错误。

我怎样才能做到这一点?

您可以使用 static_assert 来确保 Argument 是带有辅助结构的 Arguments 的一部分。

#include <array>
#include <iostream>

template <typename... T>
struct contains;

template <typename T>
struct contains<T> : std::false_type {};

template <typename T, typename U, typename... Rest>
struct contains<T, U, Rest...> : contains<T, Rest...>  {};

template <typename T, typename... Rest>
struct contains<T, T, Rest...> : std::true_type {};

template<typename T_, std::size_t size_>
struct arg
{
    using T = T_;
    static constexpr std::size_t size = size_;
};

template<typename... Arguments>
struct Foo
{
    template<typename Argument>
    std::array<typename Argument::T, Argument::size>& getArray() // specializations of all args in Arguments should be generated
    {
        static_assert(contains<Argument, Arguments...>(), "Invalid type");
        static std::array<typename Argument::T, Argument::size> arr;
        return arr;
    }
};

int main()
{
    Foo<arg<int, 10>, arg<float, 10>, arg<float, 1>> myFoo;
    myFoo.getArray<arg<int, 10>>()[5] = 7;
    myFoo.getArray<arg<float, 10>>(); // should return a different array than the line above
    //myFoo.getArray<arg<bool, 1>>(); // should NOT work because arg<bool, 10> is was not passed to Foo

    Foo<arg<int, 10>, arg<float, 10>, arg<float, 1>> myFoo2;
    std::cout << myFoo2.getArray<arg<int, 10>>()[5];

    Foo<arg<int, 10>, arg<float, 10>, arg<double, 1>> myFoo3;
    std::cout << myFoo3.getArray<arg<int, 10>>()[5];
}

还想指出,如代码所示,myFoomyFoo2 returns 是相同的数组,因为它们是完全相同的类型。

另一方面,

myFoo3 是一个单独的类型,这意味着 getArray 成员函数是一个单独的函数,并且有自己的相同类型数组的副本。