如果变量的值在编译时已知/未知,则特殊化

Specialize if value of a variable is known/unknown at compile time

本文关键字:未知 特殊化 变量 编译 如果      更新时间:2023-10-16

如何专门化模板函数的情况下,它的参数之一的值是已知/未知在编译期间(在实际编译和运行程序之前)?

我还不知道怎么做。

想法一:

#include <type_traits>
#include <iostream>
int main(void){
    int a; //value of a is not known at compile time
    bool b = (a == a); //value of b is known at compile time.
    std::is_assignable< constexpr bool, bool >::value
}
//g++ magic.cpp -std=c++14
//error: wrong number of template arguments (1, should be 2)
// std::is_assignable< constexpr bool, bool >::value

想法二:

#include <type_traits>
#include <iostream>
int main(void){
    const int a=1;
    int b = (a == a);
    std::cout <<  __builtin_constant_p (a)  << std::endl;
    std::cout <<  __builtin_constant_p (b)  << std::endl;
}
//prints 0 and 0.

我想你指的是参数的类型,对吧?对于部分模板特化,值无关紧要…

然后:这不可能。

模板的参数类型必须在编译时已知。编译器还应该如何生成正确的代码?

同样,对于部分模板特化,由于同样的原因,类型必须在编译时已知。

我来得有点晚了,我的部分答案可能不太令人满意,但下面是:


编译时无法通过检查判断值是否已知的情况:

  1. constexpr函数的非模板输入值
  2. 模板参数提供的类型的成员

我不知道如何处理问题1,但对于问题2,我们可以使用SFINAE:寻找具有已知名称的特定成员(在下面的示例中为X),并尝试将其作为模板参数发送,如下所示:

// like std::void_t, but for value inputs:
template <auto>
using v_to_void_t = void;
//////////////////////////////////////////////////////////////
template <class, class = void>
struct has_constexpr_X
    : std::false_type {};
template <class T>
struct has_constexpr_X <T, v_to_void_t<T().X>>
    : std::true_type {};
template <class T>
constexpr bool has_constexpr_X_v
    = has_constexpr_X<T>::value;

使用例子:

struct HasStaticConstexprX {
    static constexpr int X = 2;
};
struct HasStaticConstX {
    static const int X; // implied constexpr
};
const int HasStaticConstX::X = 3;
struct HasStaticX {
    static int X;
};
int HasStaticX::X = 4;
struct HasConstX {
    const int X;
};
int main () {
    static_assert(has_constexpr_X_v<HasStaticConstexprX>);
    static_assert(has_constexpr_X_v<HasStaticConstX>);
    static_assert(! has_constexpr_X_v<HasStaticX>);
    static_assert(! has_constexpr_X_v<HasConstX>);
}

演示:

  • c++ 17
  • c++ 14