这是一个简化的例子,代码用于生成任意值的序列(在std::iota
意义上)和不同类别的迭代器:
struct delta
{
template<typename I>
void inc(I& i) { ++i; }
template<typename I>
I next(I i) { inc(i); return i; }
};
有许多类delta
,每个类都以不同的方式定义inc
,例如--i
,i += step
,i -= step
,i *= step
,f(i)
等。函数next
保持不变,实际上是在基类中共享。< / p>
我们正在next
的变异操作中生成inc
的基于值的操作。相反的做法是相同的,但是我们选择这种设计来提高性能,因为next
只能在某些初始化时调用,而inc
可能会被调用一百万次。
问题是如果某些参数是编译时常量,我想在编译时调用next
给定constexpr
参数i
。
这在C ++ 11中是不可能的,因为调用了非constexpr
函数inc
。只需更改为
template<typename I>
constexpr I next(I i) { inc(i); return i; }
或
template<typename I>
constexpr I next(I i) { return inc(i), i; }
不起作用。当然,我们可以提供另一个特殊功能,如
template<typename I>
constexpr I next(I i) { return i + 1; }
但这是代码重复太多,因为有许多类如delta
和许多其他操作,如inc/next
。
我已经看到constexpr
函数限制为relaxed in C++14,但我不能achieve this in practice yet。
所以:
修改
似乎inc
也应该constexpr
(尽管void
)。这个works就铿锵声3.4:
struct delta
{
template<typename I>
constexpr void inc(I& i) { ++i; }
template<typename I>
constexpr I next(I i) { inc(i); return i; }
};
...但不是在gcc 4.8.2上。那么上面的代码是正确的C ++ 14吗? gcc只是时间问题吗?
答案 0 :(得分:4)
根据这个page C ++ 14s广义的constexpr函数尚不支持,这个例子对gcc不起作用就不足为奇了。
我认为编辑中的源代码是有效的C ++ 14,可用的草案标准here包含,第126页(第5.19节)一个与您非常相似的示例(没有模板,非成员)功能,他们使用临时):
constexpr int incr(int &n) {
return ++n;
}
constexpr int g(int k) {
constexpr int x = incr(k);// error: incr(k) is not a core constant
// expression because lifetime of k
// began outside the expression incr(k)
return x;
}
constexpr int h(int k) {
int x = incr(k);
// OK: incr(k) is not required to be a core
// constant expression
return x;
}
constexpr int y = h(1); // OK: initializes y with the value 2
// h(1) is a core constant expression because
// the lifetime of k begins inside h(1)
如果我对标准的阅读是正确的,那么你的成员函数应该无关紧要,因为“this”没有被评估,而且代码似乎没有违反§5.19中所列出的任何其他规则(2 )。