相关疑难解决方法(0)

在默认模板参数中调用constexpr

在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)

c++ gcc clang constexpr c++11

12
推荐指数
1
解决办法
2017
查看次数

我可以在编译时检测到编译时常量的"函数参数"

我可以在编译时检测"函数参数" 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()等.

c++ optimization constexpr c++11

12
推荐指数
1
解决办法
885
查看次数

如果在编译时未知表达式,则通过静态断言

我想实现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)

c++

11
推荐指数
1
解决办法
219
查看次数

如何在编译期间计算数组大小(不接受指针)?

给定一个数组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)

救命?

c++ arrays templates enable-if c++11

9
推荐指数
1
解决办法
711
查看次数

`constexpr` 函数的 `noexcept` 行为

[expr.unary.noexcept]的措辞在C++17 中发生了变化。


以前(n4140, 5.3.7 noexcept operator [expr.unary.noexcept]),我的重点是

  1. 如果在潜在求值的上下文中表达式将包含,则 noexcept 运算符的结果为 false

    (3.1) 对不具有非抛出异常规范 ([except.spec]) 的函数、成员函数、函数指针或成员函数指针的潜在求值调用,除非调用是常量表达式 ([ expr.const]) ...


现在17.6.2.6 noexcept 运算符 [expr.unary.noexcept]):

  1. 除非表达式可能抛出异常 ([except.spec]),否则noexcept 运算符的结果为

然后在14.5 异常规范 [except.spec] 中

  1. 如果函数声明没有 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)

c++ language-lawyer noexcept constexpr c++17

8
推荐指数
1
解决办法
260
查看次数

尝试实现is_constexpr()-编译器不同

以下是三次尝试实现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)

c++ language-lawyer constexpr c++17

6
推荐指数
1
解决办法
157
查看次数

在 constexpr 评估上分支/在 constexpr 上重载

设置:

我有一个使用 SIMD 内在函数的函数,并希望在一些 constexpr 函数中使用它。

为此,我需要使其成为 constexpr。但是,SIMD 内在函数没有标记为 constexpr,编译器的常量评估器无法处理它们。

我尝试用执行相同操作的 C++ constexpr 实现替换 SIMD 内在函数。该函数在运行时变慢了 3.5 倍,但我能够在编译时使用它(是吗?)。

问题

如何在常量表达式中使用此函数而不会在运行时减慢程序速度?

一些想法:

  • 为所有编译器添加对编译器常量表达式求值器的常量求值所有 SIMD 内在函数的支持:可能是正确的解决方案,但这是一项不可能完成的任务。

更务实的解决方案是:

  • 重载函数取决于它是否在常量表达式中执行(即提供 constexpr 和非 constexpr 版本)。
  • 或者,在 constexpr 和运行时实现之间的 constexpr 函数内以某种方式分支(即,在分支中检测函数是否在常量表达式内执行)。

无论如何,我愿意接受任何解决我问题的建议。

提示

  • @RMartinhoFernandes 在 Lounge 中建议使用__builtin_constant_p来检测函数参数是否都是常量表达式,在这种情况下,编译器希望至少尝试在编译时评估函数。

失败的尝试

  • @ Jarod42 提出了只使用两个独立函数的直接建议。我想简单地指出为什么这行不通,因为它不是微不足道的。该解决方案假设在调用站点知道函数是否会被 constexpr 评估。但这种情况并非如此。考虑一个调用我的函数的 constexpr 函数,它应该选择哪个版本的函数?它必须选择 constexpr 一个才能编译,但“外部” constexpr 函数仍然可以在运行时评估。在这种情况下,它将使用“慢”编译时实现,因此,这种方法不能解决问题。

c++ simd intrinsics constexpr c++14

5
推荐指数
1
解决办法
832
查看次数

如果 consteval 需要什么?

C++23 将引入if consteval. 这将在哪里使用,它与constexpr if?

c++ constexpr consteval c++23

5
推荐指数
1
解决办法
304
查看次数

有没有办法检测可以标记为“constexpr”的函数?

鉴于我想改进我的 C++ 代码库。第一步是将函数标记为constexpr满足所用 C++ 标准的要求。有没有办法判断一个函数是否可以被标记constexpr

我想出的唯一方法是添加constexpr到单个实例,运行编译器,并检查它是否抱怨它不是constexpr。重复直到检查完所有实例。这种方法无法扩展。

相关:我们应该尽可能使用 constexpr 吗?

c++ constexpr

4
推荐指数
1
解决办法
174
查看次数

如果已知则使用编译时常量

我有一些神秘类型的值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)

c++ templates compile-time

3
推荐指数
1
解决办法
69
查看次数