三元运算符在编译时未计算——模板元编程

问题描述 投票:0回答:1
template <int T, typename V>
struct Get;

template <int T>
struct Get<T, Vector<>> {
    static_assert(std::false_type::value, "Vector Index out of bounds!");
};

template <int T, int X, int... Xs>
struct Get<T, Vector<X, Xs...>> {
    static const int value = (T == 0) ? X : Get<T - 1, Vector<Xs...>>::value;
};

// ^ Your code goes here

static_assert(Get<0, Vector<0,1,2>>::value == 0);

我正在尝试这段代码来获取向量的特定元素。但是,为什么我会在这里收到如下错误:

p1.cpp: In instantiation of ‘struct Get<-3, Vector<> >’:
p1.cpp:380:69:   recursively required from ‘const int Get<-1, Vector<1, 2> >::value’
p1.cpp:380:69:   required from ‘const int Get<0, Vector<0, 1, 2> >::value’
p1.cpp:385:38:   required from here
p1.cpp:375:40: error: static assertion failed: Vector Index out of bounds!
  375 |         static_assert(std::false_type::value, "Vector Index out of bounds!");
      |                       ~~~~~~~~~~~~~~~~~^~~~~
p1.cpp:375:40: note: ‘std::integral_constant<bool, false>::value’ evaluates to false
p1.cpp: In instantiation of ‘const int Get<-2, Vector<2> >::value’:
p1.cpp:380:69:   recursively required from ‘const int Get<-1, Vector<1, 2> >::value’
p1.cpp:380:69:   required from ‘const int Get<0, Vector<0, 1, 2> >::value’
p1.cpp:385:38:   required from here
p1.cpp:380:76: error: ‘value’ is not a member of ‘Get<-3, Vector<> >’
  380 |         static const int value = (T == 0) ? X : Get<T - 1, Vector<Xs...>>::value;

为什么三元运算符没有正确求值,导致T变成-3?

c++ templates c++17 conditional-operator
1个回答
0
投票

即使三元运算符的条件在编译时已知,所有操作数仍然需要有效并遵循正常的 odr 使用规则。

Get<T - 1, Vector<Xs...>>::value
仍必须被验证为有效表达式,这意味着
Get<T - 1, Vector<Xs...>>
将被实例化。

因此,您将继续递归实例化

Get<T - 1, Vector<Xs...>>
,并且
T
变得越来越小,直到最终达到递归实例化的实现限制或
T-1
溢出,导致模板参数格式错误。

为了避免实例化,您应该声明部分特化而不是使用三元运算符:

template <int T, int X, int... Xs>
struct Get<T, Vector<X, Xs...>> {
    static const int value = Get<T - 1, Vector<Xs...>>::value;
};

template <int X, int... Xs>
struct Get<0, Vector<X, Xs...>> {
    static const int value = X;
};

另外,一般情况下,对于

constexpr
,使用
const
而不是
value
会更好。

© www.soinside.com 2019 - 2024. All rights reserved.