标签: constexpr

在编译时验证std :: initializer_list的内容

我试图在编译时确定a std::initializer_list中的所有值是否唯一.我找到了一个解决方案,以确定列表的大小,但无法将其应用于内容.我已尝试使用自由函数和构造函数,但这两种方法都导致GCC 4.7.2出现以下错误.

错误:静态断言
错误的非常量条件:'begin'不是常量表达式

我意识到std::initializer_list没有声明成员,constexpr但我希望有一个像尺寸验证的解决方案.是否可以使用以下内容在编译时验证内容?

#include <initializer_list>

template<typename InputIterator>
constexpr bool Validate(InputIterator begin, InputIterator end)
{
    static_assert(*begin == *end, "begin and end are the same");
    //  The actual implemetnation is a single line recursive check.
    return true;
}

template<typename InputType>
constexpr bool Validate(const std::initializer_list<InputType>& input)
{
    // "-1" removed to simplify and eliminate potential cause of error
    return Validate(input.begin(), input.end() /* - 1 */);
}

int main()
{
    Validate({1, 2, 1});
}
Run Code Online (Sandbox Code Playgroud)

c++ validation initializer-list constexpr c++11

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

clang 3.5 constexpr inconsistency - 使用double但不是int时出错

使用constexpr中的boost数学常量并建议OP使用boost的模板函数constexpr而不是非模板化常量来平息clang错误后,我决定尝试查看哪些条件会重现clang中的错误.让我们尝试复制boost的宏扩展到:

namespace double_constants{ static const double name = 25; }

static constexpr double SEC3 = double_constants::name;
Run Code Online (Sandbox Code Playgroud)

这给出了以下错误(跟随Coliru)

clang++ -std=c++1y -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp:5:25: error: constexpr variable 'SEC3' must be initialized by a constant expression
static constexpr double SEC3 = double_constants::name;
                        ^      ~~~~~~~~~~~~~~~~~~~~~~
main.cpp:5:32: note: read of non-constexpr variable 'name' is not allowed in a constant expression
static constexpr double SEC3 = double_constants::name;
                               ^
main.cpp:3:49: note: declared here
namespace double_constants{ static …
Run Code Online (Sandbox Code Playgroud)

c++ clang constexpr c++11

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

C语言中的constexpr(或等效语言)

我正在尝试使用哈希函数在C中使用基于字符串的开关表达式。我已经能够使用'constexpr'使它与干净的语法一起使用,并且Clang / LLVM转换为C ++,即使代码是C。

但是,将其作为C ++进行编译当然会有一些奇怪的副作用,例如缺少void *隐式转换会变得很尴尬。

因此,问题是如何解决这个难题(为什么不将C11委员会的掌声压在C规范上)

  1. 有没有办法用C打开constexpr选项?
  2. 有没有办法让C ++启用隐式void *强制转换?
  3. 是否有另一种干净的方法可以在C11 / C99中进行编码,而无需重新计算哈希值?

这是我当前的示例代码:

constexpr uint64 cHash(char const* text, uint64 last_value = basis)
{
    return *str ? cHash(text+1, (*text ^ last_value) * prime) : last_value;
}

void SwitchFunction(char const* text)
{
    switch(Hash(text))
    {
        case cHash("first"):
            break;
        case cHash("second"):
            break;
        case cHash("third"):
            break;
        default:
            break;
    }
}
Run Code Online (Sandbox Code Playgroud)

c c++ clang constexpr

8
推荐指数
4
解决办法
5130
查看次数

为什么constexpr必须是静态的?

尝试使用constexpr属性创建结构的成员而不是静态会导致编译器错误(请参阅下文).这是为什么?对于单个常量值,我将在内存中使用此值,直到程序终止而不仅仅是struct的范围?我应该回去使用宏吗?

struct foo
{
  constexpr int n = 10;
  // ...
};

error: non-static data member cannot be constexpr; did you intend to make it static?
Run Code Online (Sandbox Code Playgroud)

c++ clang constexpr c++11

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

Constexpr技巧

我认为这是不可能的,但我想在放弃之前问你.

我想要像constexpr增量一样的东西.

#include  <iostream>

constexpr int inc() {

  static int inc = 0;
  return inc++;
}

class Foo {

  static const int  Type = inc();
};

class Foo2 {

  static const int  Type = inc();
};

int main() {

  std::cout << "Foo1 " << Foo1::Type << st::endl;
  std::cout << "Foo2 " << Foo2::Type << st::endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我想把它称为某些类而不是手动(我使用CRTP),为每个类提供不同的类型,但类型需要是const.无论如何在C++中实现类似的东西?(C++ 17 + TS)

c++ metaprogramming constexpr

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

在constexpr函数中返回一个C字符串:为什么编译器没有警告?

请考虑以下代码:

constexpr auto f()
{
    auto str = "Hello World!";
    return str;
}

int main(int argc, char* argv[])
{
    static constexpr auto str = f();
    std::cout << str << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是正常的,我的编译器没有显示任何警告?它是否定义了行为?我能保证程序会显示"Hello World!"吗?我希望"Hello World!"不要超出功能范围......

c++ c-strings string-literals constexpr c++14

8
推荐指数
2
解决办法
642
查看次数

C++ constexpr:在编译时计算std数组

我想将"数组"转换bool为整数序列.所以我需要std::array在编译时计算一个.

这是我的代码

#include <array>

template<typename InputIt, typename T >
inline constexpr typename std::iterator_traits<InputIt>::difference_type
count( InputIt first, InputIt last, const T &value ) {
    typename std::iterator_traits<InputIt>::difference_type ret = 0;
        for (; first != last; ++first) {
            if (*first == value) {
                ret++;
            }
        }
        return ret;
}

template<bool ..._values>
struct keep_value {
    static constexpr std::size_t numberOfValues = sizeof...(_values);
    static constexpr bool values[] = {_values...};
    static constexpr std::size_t numberToKeep = count(values, values + numberOfValues, true);

    static constexpr std::array<std::size_t, …
Run Code Online (Sandbox Code Playgroud)

c++ template-meta-programming variadic-templates constexpr c++14

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

可以在 constexpr 函数中声明静态局部变量吗?

可以在函数中使用static局部变量吗?constexpr例如:

#include <string_view>
#include <utility>

enum class axis {
    x, y, z
};

constexpr std::string_view axis_name(axis a) {
    // use static constexpr to avoid putting the table onto the stack
    static constexpr std::string_view names[] {
        "x", "y", "z"
    };
    return names[std::to_underlying(a)];
}

constexpr auto x_name = axis_name(axis::x);
Run Code Online (Sandbox Code Playgroud)

GCC 12 无法编译此错误:

<source>:9:39: error: 'names' defined 'static' in 'constexpr' context
    9 |     static constexpr std::string_view names[] {
      |                                       ^~~~~
Run Code Online (Sandbox Code Playgroud)

其他编译器允许它。规则是什么?什么时候允许?

  • 我们可以static一般使用,或者
  • 只是static const,或者
  • 只是 …

c++ constants constexpr c++23

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

std::initializer_list 什么时候可以是 constexpr?

根据 cppreference.com,std::initializer_lists 具有constexpr 构造函数constexpr 大小方法(C++14 起)。

尽管我使用的编译器似乎同意 constexpr 初始值设定项列表的大小确实是 constexpr,但在某些情况下,它不相信我的列表是 constexpr。由于 std::initializer_lists 可能涉及一些“编译器魔法”,我开始想知道 constexpr 是否不适用于它们,其方式与适用于非魔法对象的方式完全相同。

我跳到 Compiler Explorer 上,发现主要编译器在这个主题上并不一致

那么以下四种情况的正确行为(根据标准)是什么?

#include <initializer_list>

using size_type = std::initializer_list<int>::size_type;

template <typename T>
size_type Foo(std::initializer_list<T> const &list) {
    return list.size();
}

int main() {
    // 1.  Example based on
    // https://en.cppreference.com/w/cpp/utility/initializer_list/size
    // gcc: works
    // clang: no viable c'tor or deduction guide
    // msvc: works
    static_assert(std::initializer_list{1, 2, 3}.size() == 3);

    // 2.  Make a constexpr std::initializer_list<T> with T …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer constexpr stdinitializerlist c++20

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

可以将具有未初始化字段的对象安全地添加到 std::vector 中吗?

在以下程序中,struct 的默认构造函数A不会初始化其字段v。然后在常量表达式中,std::vector<A>放置有A()对象:

#include <vector>

struct A {
  constexpr A() noexcept {}
  int v;
};

constexpr bool f() {
    std::vector<A> as;
    as.reserve(1);
    as.emplace_back();
    return true;
}
static_assert( f() );
Run Code Online (Sandbox Code Playgroud)

MSVC 编译器抱怨读取未初始化的变量:

<source>(14): error C2131: expression did not evaluate to a constant
<source>(11): note: failure was caused by a read of an uninitialized symbol
<source>(11): note: see usage of 'A::v'
Run Code Online (Sandbox Code Playgroud)

但 GCC 和 Clang 都对该程序很满意。在线演示: https: //godbolt.org/z/addx11aTT

这里哪个编译器是正确的?

c++ vector language-lawyer constexpr

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