在编译时,如果变量的值已知/未知,则进行专业化

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

提问人:hamster on wheels 提问时间:9/28/2016 最后编辑:hamster on wheels 更新时间:4/9/2022 访问量:635

问:

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

我还不知道怎么回事。

想法 1:

#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

想法 2:

#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.
C++ 模板 元编程

评论

2赞 hamster on wheels 9/28/2016
为什么要投反对票?“这做不到”是一个可以接受的答案。
0赞 Konrad Rudolph 9/28/2016
如果我理解正确,那么这将需要在 constexpr 上重载。— 做不到。
0赞 hamster on wheels 9/28/2016
@Konrad鲁道夫。如果我没看错这个答案,它说一个函数不能有参数。我正在考虑按特征进行专业化,而不是重新定义......或者是否有任何可行的方法。constexprconstexpr
0赞 Konrad Rudolph 9/28/2016
结果是一样的:你需要一个参数规范,正如答案所说,它不存在。我不认为这可以通过我可能弄错的特征来模仿。您能够实现的最好结果是检查参数是否为。但是,有些非编译时值仍满足此值类别。constexpr

答:

0赞 Rene 9/28/2016 #1

好吧,我猜你的意思是论点的类型,对吧?值对于部分模板专用化无关紧要...

然后:这做不到。

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

此外,对于部分模板专用化,出于同样的原因,必须在编译时知道类型。

评论

0赞 hamster on wheels 9/28/2016
井。但是“参数在编译时已知/未知”在编译时是已知的。我想知道以下情况是否可行:如果参数已知(在编译时),请将模板专用于版本 A;否则,请将模板专用于版本 B。
1赞 Rene 9/28/2016
我很难想象在编译时参数类型应该是未知的。请提供源代码示例。
0赞 hamster on wheels 9/28/2016
这与类型无关。这是价值。 alone 不指定值。 指定在编译时已知的值。对于 ,的值在编译时是已知的。int a;constexpr int a = 6;int a; bool b = (a == a);b
1赞 Rene 9/28/2016
好的,现在我们已经清除了它,您还能提供示例源代码吗?你想实现类似 std::get<> 方法的东西吗?
0赞 Elliott 4/9/2022 #2

我来晚了一点,我的部分回答可能不是很令人满意,但这里是:


我们无法从检查中判断某个值在编译时是否已知的情况:

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

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

// 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>);
}

演示: