在C++ 11中,我使用constexpr函数作为模板参数的默认值 - 它看起来像这样:
template <int value>
struct bar
{
static constexpr int get()
{
return value;
}
};
template <typename A, int value = A::get()>
struct foo
{
};
int main()
{
typedef foo<bar<0>> type;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
G ++ 4.5和4.7编译它,但Clang ++ 3.1没有.来自clang的错误消息是:
clang_test.cpp:10:35: error: non-type template argument is not a constant expression
template <typename A, int value = A::get()>
^~~~~~~~
clang_test.cpp:17:19: note: while checking a default template argument used here
typedef foo<bar<3>> type;
~~~~~~~~~^~
clang_test.cpp:10:35: note: undefined function …Run Code Online (Sandbox Code Playgroud) 我可以在编译时检测"函数参数" 1是否是编译时常量?
例如,一个函数print(int i)可以"constant 5"在被调用时打印,print(5)但"non-constant 5"如果被调用为print(i)where,i则是一些非常量变量.特别是,在"is constant"分支中,我应该能够将其i视为constexpr,包括将其用于模板参数等.
宏技巧,模板元编程和SFINAE技巧都可以.理想情况下它是可移植的,但是编译器特定的解决方案总比没有好.
如果存在"错误否定"则可以 - 即,如果常量值有时被检测为非常数(例如,禁用某些优化时).
如果解决方案可以检测到常量值何时间接传递给函数(例如,当一个常量值传递给调用的中间函数print并且随后内联将常量暴露给print)时,可以获得奖励积分.最后一种行为显然取决于优化.
如果它自然延伸到多个参数,则可获得双倍奖励
如果一个人可以使用和不带constexpr参数重载函数的版本,这可能是直截了当的,但你不能.
1我在这里引用"函数参数",因为解决方案并不严格要求在函数内(或在具有特殊参数的调用者/被调用者边界)检测此状态 - 它只需要像函数一样出现给调用者但是可以使用宏或其他技巧,如静态对象operator()等.
我想实现my_static_assert与c ++ 17单参数稍有不同的方法static_assert:如果在编译时my_static_assert 不知道里面的条件,则应该通过。
my_static_assert以下示例中的第二个应该通过,但是如果我使用static_assert它将会失败。
#include <iostream>
int x, y;
constexpr int f1() { return 0; }
constexpr int f2() { return 0; }
int f3() { return x; }
int f4() { return y; }
constexpr int sum(int a, int b) { return a + b; }
int main() {
std::cin >> x >> y;
// it should fail
my_static_assert(sum(sum(f1(), f2()), sum(f1(), f1())) != 0);
// it should …Run Code Online (Sandbox Code Playgroud) 给定一个数组a,我想countof(a)将数组中的元素数作为编译时常量.如果我有一个指针p,我想countof(p)不编译.这似乎应该是(1)直截了当,(2)通常涵盖在SO中,但(1)我无法使它工作,并且(2)搜索SO没有发现任何东西.
这是我的尝试.
#include <cstddef>
#include <type_traits>
template<typename T, std::size_t n,
typename = typename std::enable_if<std::is_array<T>::value>::type>
constexpr std::size_t countof(T (&)[n]) { return n; }
template<typename T,
typename = typename std::enable_if<std::is_pointer<T>::value>::type>
void countof(T*) = delete;
int main()
{
int a[10];
auto asize = countof(a); // should compile
static_assert(countof(a) == 10,
"countof(a) != 10!");
int *p;
auto psize = countof(p); // shouldn't compile
}
Run Code Online (Sandbox Code Playgroud)
救命?
[expr.unary.noexcept]的措辞在C++17 中发生了变化。
以前(n4140, 5.3.7 noexcept operator [expr.unary.noexcept]),我的重点是:
- 如果在潜在求值的上下文中表达式将包含,则 noexcept 运算符的结果为 false
(3.1) 对不具有非抛出异常规范 ([except.spec]) 的函数、成员函数、函数指针或成员函数指针的潜在求值调用,除非调用是常量表达式 ([ expr.const]) ...
现在1(7.6.2.6 noexcept 运算符 [expr.unary.noexcept]):
- 除非表达式可能抛出异常 ([except.spec]),否则noexcept 运算符的结果为真。
- 如果函数声明没有 noexcept 说明符,则该声明具有潜在的抛出异常说明,除非...
但是14.5(3)的除非列表未列出constexpr,因此可能会抛出...
1 LF 在评论中添加的指向 C++17 n4659的链接。
constexpr int f(int i) { return i; }
std::cout << boolalpha << noexcept(f(7)) << std::endl;
int a = 7;
std::cout …Run Code Online (Sandbox Code Playgroud) 以下是三次尝试实现is_constexpr()根据理查德·史密斯的回答到是is_constexpr可能在C ++ 11?
版本1
template <typename T>
bool constexpr is_constexpr_impl_1(const T& x, decltype(int{(x, 0u)})) { return true; }
template <typename T>
bool constexpr is_constexpr_impl_1(const T&, ...) { return false; }
template <typename T>
bool constexpr is_constexpr_1(const T& x) { return is_constexpr_impl_1(x, 0); }
Run Code Online (Sandbox Code Playgroud)
版本2
template <typename T>
bool constexpr is_constexpr_impl_2(const T& f, decltype(int{(f(0), 0u)})) { return true; }
template <typename T>
bool constexpr is_constexpr_impl_2(const T&, ...) { return false; }
template <typename T> …Run Code Online (Sandbox Code Playgroud) 设置:
我有一个使用 SIMD 内在函数的函数,并希望在一些 constexpr 函数中使用它。
为此,我需要使其成为 constexpr。但是,SIMD 内在函数没有标记为 constexpr,编译器的常量评估器无法处理它们。
我尝试用执行相同操作的 C++ constexpr 实现替换 SIMD 内在函数。该函数在运行时变慢了 3.5 倍,但我能够在编译时使用它(是吗?)。
问题:
如何在常量表达式中使用此函数而不会在运行时减慢程序速度?
一些想法:
更务实的解决方案是:
无论如何,我愿意接受任何解决我问题的建议。
提示:
__builtin_constant_p来检测函数参数是否都是常量表达式,在这种情况下,编译器希望至少尝试在编译时评估函数。失败的尝试:
C++23 将引入if consteval. 这将在哪里使用,它与constexpr if?
鉴于我想改进我的 C++ 代码库。第一步是将函数标记为constexpr满足所用 C++ 标准的要求。有没有办法判断一个函数是否可以被标记constexpr?
我想出的唯一方法是添加constexpr到单个实例,运行编译器,并检查它是否抱怨它不是constexpr。重复直到检查完所有实例。这种方法无法扩展。
我有一些神秘类型的值T(对于这个例子,我们可以假设T是一个整数类型).我想在一些模板函数中使用此值作为模板参数(对于此示例,参数为std::integral_constant).麻烦的是,这T可能不是一个常数类型.如果它不是常量类型,我想0在我的模板函数中默认.但是,如果它是常数,我想使用值本身,因为它是已知的.
目前,我有以下(非编译)代码.
#include <type_traits>
template <typename T>
struct CompileTimeStuff {
constexpr static int value(T arg) { return 0; }
};
template <typename T>
struct CompileTimeStuff<const T> {
constexpr static int value(const T arg) { return (int)arg; }
};
template <typename T>
constexpr int magic_function(T arg) {
return CompileTimeStuff<T>::value(arg);
}
const int cvalue = 7;
int ivalue = 7;
// This should be 7, since cvalue is constant and thus known …Run Code Online (Sandbox Code Playgroud)