【问题标题】:Recursive variable templates递归变量模板
【发布时间】:2015-05-20 23:53:39
【问题描述】:

我尝试像使用其他模板一样使用变量模板,例如:我们已经知道如何使用带有template objects wrapping a static value or a enum value 的元编程来计算Fibonacci numberpower of a number

所以,我做的第一件事是尝试专门化一个模板变量,它按预期工作:

template <std::size_t VALUE> std::size_t value       = VALUE;
template <>                  std::size_t value<666u> = 1u;

std::cout << value<0u> << '\n';   // "0" as expected
std::cout << value<1u> << '\n';   // "1" as expected
std::cout << value<2u> << '\n';   // "2" as expected
std::cout << value<666u> << '\n'; // "1" as expected!!

知道变量模板特化是可能的,我尝试做一个变量模板斐波那契数:

template <std::size_t ITERATION>
std::size_t fibonacci = fibonacci<ITERATION - 1u> + fibonacci<ITERATION - 2u>;
template <> std::size_t fibonacci<1u> = 1u;
template <> std::size_t fibonacci<0u> = 0u;

int main()
{
    std::cout << fibonacci<5> << '\n'; // "8" expected;
    return 0;
}

我从Wandbox 得到的错误如下:

error: expected primary-expression before ';' token
template <std::size_t ITERATION> std::size_t fibonacci = fibonacci<ITERATION - 1u> + fibonacci<ITERATION - 2u>;
                                                                                                              ^

我不知道自己做错了什么,也不理解错误。我猜这个错误可能与我已经在使用它时尚未定义变量模板这一事实有关,所以我想知道是否有可能使用变量模板实现我的目标。

有什么提示吗?

非常感谢。

【问题讨论】:

    标签: c++ templates c++14 variable-templates


    【解决方案1】:

    我的猜测是编译器还没有正确实现变量模板。例如,clang 3.7.0 编译您的代码,但(带有一个小错误修复:fibonacci&lt;0u&gt; = 1u)输出0 而不是8fibonacci&lt;5&gt;

    但是,如果我们这样做了

    std::cout << fibonacci<0> << '\n'; // "1" expected;
    std::cout << fibonacci<1> << '\n'; // "1" expected;
    std::cout << fibonacci<2> << '\n'; // "2" expected;
    std::cout << fibonacci<3> << '\n'; // "3" expected;
    std::cout << fibonacci<4> << '\n'; // "5" expected;
    std::cout << fibonacci<5> << '\n'; // "8" expected;
    

    然后我们得到预期的结果。奇怪!

    更新由于函数模板比​​变量模板更成熟,下面是一个变通方法:

    template <std::size_t ITERATION>
    constexpr std::size_t get_fibonacci()
    {
        return get_fibonacci<ITERATION - 1u>() + get_fibonacci<ITERATION - 2u>();
    }
    
    template <>
    constexpr std::size_t get_fibonacci<0u>() {
        return 1u;
    }
    
    template <>
    constexpr std::size_t get_fibonacci<1u>() {
        return 1u;
    }
    
    template <std::size_t ITERATION>
    std::size_t fibonacci = get_fibonacci<ITERATION>();
    

    【讨论】:

    • 嗯,只有正确的代码才能达到预期的效果;如果我有错误或拼写错误,则无法为第 5 个斐波那契数获得 8 ;) 无论如何,我的问题似乎与编译器如何实现 VT 有关,因此代码有望工作是一种解脱.非常感谢!
    • 我会责怪标准,而不是编译器供应商自己
    • @PiotrS。事实证明,大多数编译器供应商都是标准委员会的成员。我的观点是,这可能只是一个时间问题,直到实现正确为止。
    • @CassioNeri 我注意到使模板及其专业化constexpr 按预期工作。我猜如果你单独使用fibonacci&lt;5&gt;,编译器不会计算以前的值(除非它是constexpr),因此它会返回0
    • @PaperBirdMaster 有趣!我同意编译器不会递归地实例化模板,除非它是constexpr。我不知道这是预期行为还是编译器错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多