【问题标题】:gcc 4.7.2 error variadic templategcc 4.7.2 错误可变参数模板
【发布时间】:2014-02-01 23:27:36
【问题描述】:

我正在尝试使用一些 TMP 和 constexpr C++11 魔法编写一个可以充当编译时数组的类。我试图实现的最终目标基本上是能够写作

Type array[Size] = {X, X, X, ..., X};

作为

Array<Type, Size, X> array;

对于任意的TypeSize(仅受编译器的递归深度限制)。这是我想出的:

template <typename T, size_t Size, T Value = T()>
struct Array
{
    template <size_t Count, T ... Elements>
    struct Helper
    {
        constexpr Helper() {}
        Helper<Count + 1, Value, Elements...> helper;

        constexpr T const *get() const
        {          
            return helper.get();
        }
    };

    template <T ... Elements>
    struct Helper<Size, Elements ...>
    {
        constexpr Helper() {}
        T array[Size] {Elements...};

        constexpr T const * get() const
        {
            return array;
        }
    };

    constexpr Array():
        helper(),
        array{helper.get()}
    {}

    Helper<0> helper;
    T const *array;

    constexpr operator T const * () 
    { 
        return array;
    }
};

会发生这种情况:Array 对象初始化了 Helper&lt;0&gt; 类型的成员,该成员本身初始化了 Helper&lt;1&gt; 类型的成员,该成员初始化了 Helper&lt;2&gt; 类型的成员 ...,添加了一个元素在每个迭代中,直到 Helper&lt;Size, ...&gt; 的专用模板被实例化。至此,可变参数包正好包含Size 元素,可以在大括号括起来的初始化列表中使用这些元素来初始化包含在最终Helper 对象中的数组。这就是神秘错误的来源:

error: ‘Elements’ was not declared in this scope

对不起?未申报?它就在那里作为模板参数。我是否忽略了一些非常明显的东西?

【问题讨论】:

  • g++ 4.8.1 也失败了。

标签: arrays templates c++11 initializer variadic


【解决方案1】:

作为一种解决方法,将 Helper 移到模板类之外是可行的。

以下可能会有所帮助:

namespace detail {

template <typename T, T value, T ... Elements>
struct ArrayHelper
{
    constexpr ArrayHelper() {}
    T array[sizeof...(Elements)] {Elements...};

    constexpr T const * get() const { return array; }
};

template <std::size_t Size, typename T, T value, T ... Elements>
struct MakeArrayHelper
{
    typedef typename MakeArrayHelper<Size - 1, T, value, value, Elements...>::type type;
};

template <typename T, T value, T ... Elements>
struct MakeArrayHelper<0, T, value, Elements...>
{
    typedef ArrayHelper<T, Elements...> type;
};

} // namespace detail

template <typename T, size_t Size, T Value = T()>
struct Array
{
    constexpr Array():
        helper(),
        array{helper.get()}
    {}

    typename detail::MakeArrayHelper<Size, T, Value>::type helper;
    T const *array;

    constexpr operator T const * () const { return array; }
};

请注意,MakeArrayHelper 可以用Size / 2 而不是Size - 1 进行递归重写,以允许更大的尺寸(因此达到更大尺寸的递归限制)。

【讨论】:

  • 非常感谢!你认为我应该提交错误报告吗?
  • @JorenHeit:确定它是否还没有出现。将您的示例最小化为最少的代码:template &lt;typename T&gt; struct S { template &lt;int V&gt; struct Inner { int a {V}; }; };
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-05
  • 2012-01-20
  • 1970-01-01
  • 1970-01-01
  • 2019-07-27
  • 1970-01-01
  • 2020-03-12
相关资源
最近更新 更多