【问题标题】:How can I deduce a template parameter type in C++11?如何在 C++11 中推断模板参数类型?
【发布时间】:2020-06-25 01:31:52
【问题描述】:

我正在尝试编写一个强制constexpr 评估的函数。一个模板。我写了这个,但它只适用于int(注意,GCC 会给出递归深度错误):

#include <iostream>

template<int val>
constexpr int force_constexpr() { return val; }

constexpr int triangle(int n)
{
    return n ? n + triangle(n - 1) : 0;
}

int main(void)
{
    std::cout << force_constexpr<triangle(0x200)>() << '\n';
}

请注意,这仅用于演示目的;我知道可以用(n+1)*n/2计算三角形数。

然后我尝试编写一个通用函数,但是效果不佳。这是一个简单的错误(并不奇怪,因为它在定义 T 之前使用了 T):

template<T val, typename T = decltype(val)>
constexpr T force_constexpr() { return val; }

就这样(这显然行不通;它是一个嵌套模板):

template<typename T>
template<T val>
constexpr T force_constexpr() { return val; }

这需要传递参数的类型:

template<typename T, T val>
constexpr T force_constexpr() { return val; }

如何在不将类型作为参数传递给模板的情况下做到这一点?或者换句话说,如何推导出模板参数类型?

我正在寻找 C++11 解决方案,但欢迎其他标准的解决方案。

【问题讨论】:

    标签: c++ c++11 templates constexpr


    【解决方案1】:

    您正在寻找 C++17 中的 auto 模板参数:

    #include <iostream>
    
    template<auto T>
    auto *singleton()
    {
        static const decltype(T) solo{T};
    
        return &solo;
    }
    
    int main()
    {
        const int *p=singleton<42>();
    
        std::cout << "The meaning of life: " << *p << std::endl;
    
        return 0;
    }
    

    指定模板参数为auto,并使用decltype推断其类型。

    我不相信这在 C++17 之前是可能的,因为this is precisely the use case for which auto template parameters were added to the standard。从概念上讲,在那之前无法做到这一点。

    【讨论】:

      【解决方案2】:

      C++17 引入auto 作为非类型模板参数:

      template <auto val>
      constexpr auto force_constexpr() { return val; }
      

      之前,你确实被屏蔽了

      template<typename T, T val>
      constexpr T force_constexpr() { return val; }
      

      你可以引入 MACRO 来简化使用:

      #define AUTO(v) decltype(v), (v)
      

      然后

      std::cout << force_constexpr<AUTO(triangle(0x200))>() << '\n';
      

      【讨论】:

        猜你喜欢
        • 2023-03-31
        • 2015-02-06
        • 1970-01-01
        • 2021-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-07
        • 2020-07-09
        相关资源
        最近更新 更多