【问题标题】:integer_sequence and default parameter valueinteger_sequence 和默认参数值
【发布时间】:2015-06-20 15:34:15
【问题描述】:

直接使用默认参数值生成整数序列如下导致硬错误(编译器clang-3.6):

#include <iostream>
#include <utility>

#include <cstdlib>

template< std::size_t M, std::size_t N > // say M - arity, N - number of types
struct test
{

    template< std::size_t ...i >
    void
    operator () (std::index_sequence< i... > = std::make_index_sequence< M >{}) const
    {
        std::size_t indices[M];
        for (std::size_t & m : indices) {
            m = 0;
        }
        for (;;) {
            (std::cout << ... << indices[i]) << std::endl;
            std::size_t m = 0;
            for (;;) {
                std::size_t & n = indices[m];
                ++n;
                if (n != N) {
                    break;
                }        
                n = 0; 
                if (++m == M) {
                    return;
                }
            }
        }
    }

};

int
main()
{
#if 0
    test< 3, 3 >{}(); // hard error
#else
    test< 3, 3 >{}(std::make_index_sequence< 3 >{}); // ugly workaround
#endif
    return EXIT_SUCCESS;
}

看起来很奇怪,因为简单的替换按预期工作。

为什么会这样?为什么在上述情况下无法分配默认参数,但显式分配有效?

const &amp;&amp;&amp; 附加到参数类型没有任何作用。

【问题讨论】:

  • 似乎期望类型完全等价。 std::make_index_sequence&lt; M &gt;::operator std::index_sequence&lt; i... &gt; () const 将是非常有用的功能。
  • @LightnessRacesinOrbit 虽然使用struct I { constexpr operator std::index_sequence&lt; 0, 1, 2 &gt; () const { return {}; } }; 的实例作为默认值没有意义。 coliru.stacked-crooked.com/a/6029f0ba22cde57b
  • 您在没有参数的情况下调用operator()(),因此i... 被推断为一个空包。您现在需要进行从 index_sequence&lt;0, ..., M-1&gt;index_sequence&lt;&gt; 的转换,除非 M 为 0,否则这是不可能的。
  • @0x499602D2 有趣的解释,但从 clang 的错误描述中并不明显。谢谢。

标签: c++ c++11 default-value c++14


【解决方案1】:

模板参数不能从默认参数推导出来。这就是为什么我们通常在构建序列之前委托给辅助函数:

void operator()() const {
    helper(std::make_index_sequence<M>{});
}

template<std::size_t... i>
void helper(std::index_sequence<i...>) const;

【讨论】:

  • 这种限制的根本原因是什么?
  • @Orient 该标准只是将其列为非推断上下文。直到我读到这个stackoverflow.com/a/9629112/701092,我才知道它的基本原理
  • @Orient IMO 更好的解释方式是,在为重载解析创建候选集时,编译器需要执行模板参数推导。如果可以从中推断出模板参数,则默认参数可能会导致意外/不需要的行为。
猜你喜欢
  • 2019-05-15
  • 2013-10-08
  • 1970-01-01
  • 2015-09-09
  • 2012-05-04
  • 1970-01-01
  • 1970-01-01
  • 2018-07-16
  • 2016-08-23
相关资源
最近更新 更多