标签: constexpr

在默认模板参数中调用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
查看次数

查找表与constexpr

我正在寻找创建一个坐标查找表,如:

int a[n][2] = {{0,1},{2,3}, ... }
Run Code Online (Sandbox Code Playgroud)

对于给定的n,在编译时创建.我开始研究constexpr,但似乎是一个函数返回a constexpr std::vector<std::array <int, 2> >不是一个选项,因为我得到:

invalid return type 'std::vector<std::array<int, 2ul> >' of constexpr function
Run Code Online (Sandbox Code Playgroud)

如何创建这样的编译时数组?

c++ constexpr c++11

12
推荐指数
2
解决办法
9153
查看次数

constexpr void函数被拒绝

我有这个非常简单的功能,无法编译.

constexpr void func()
{
}
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:

error: invalid return type 'void' of constexpr function 'constexpr void func()'

     constexpr void func()
Run Code Online (Sandbox Code Playgroud)

在C++ 14中,void是一个文字类型[§3.9/ 10]:

类型是文字类型,如果它是:

  • 无效; 要么
  • 标量类型; 要么
  • 参考类型; 要么
  • 一个文字类型的数组; 要么
  • 具有以下所有属性的类类型(第9节):
    • 它有一个简单的析构函数,
    • 它是聚合类型(8.5.1)或至少有一个constexpr构造函数或构造函数模板,它不是复制或移动构造函数,并且
    • 它的所有非静态数据成员和基类都是非易失性文字类型.

有人能解释为什么这是无效的吗?

c++ return-type language-lawyer constexpr c++14

12
推荐指数
2
解决办法
3312
查看次数

用const char*const解释constexpr

我有以下代码:

static constexpr const char*const myString = "myString";
Run Code Online (Sandbox Code Playgroud)

你能解释一下有什么区别:

static const char*const myString = "myString";
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们与constexpr有什么新鲜事?

c++ const constexpr c++11

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

为什么lambda不会从达到范围捕获类型const double,但const int是?

我似乎无法理解为什么下面的类型为const int的代码编译:

int main()
{
  using T = int;
  const T x = 1;
  auto lam = [] (T p) { return x+p; };
}
$ clang++ -c lambda1.cpp  -std=c++11
$
Run Code Online (Sandbox Code Playgroud)

而这个类型为const double的那个不是:

int main()
{
  using T = double;
  const T x = 1.0;
  auto lam = [] (T p) { return x+p; };
}
$ clang++ -c lambda2.cpp  -std=c++11
lambda1.cpp:5:32: error: variable 'x' cannot be implicitly captured in a lambda with no capture-default specified
  auto lam = [] …
Run Code Online (Sandbox Code Playgroud)

c++ lambda constexpr c++11

12
推荐指数
2
解决办法
832
查看次数

为什么lambda在转换为函数指针时不能在constexpr上下文中使用?

考虑一个例子:

template <void (*Foo)()>
struct S {
};

int main() {
    struct A {
        static void x() { }
    };
    S<&A::x> s;
}
Run Code Online (Sandbox Code Playgroud)

代码在clang中编译,gcc认为x没有链接...对于非常类似的例子,只是在使用lambda表达式时:

template <void (*Foo)()>
struct S {
};

int main() {
    auto lambda = []{};
    S<+lambda> s;
}
Run Code Online (Sandbox Code Playgroud)

gcc和clang都同意不编译代码:根据gcc,由unary +返回的函数没有链接,相反,clang状态表示对该函数的强制转换操作符未声明为constexpr.是否有任何理由不允许lambda强制转换为在constexpr上下文中使用的函数指针?

查找编译器和现场演示产生的以下错误:

gcc:

prog.cc:7:14:错误:'main():::: _ FUN'不是类型'void(*)()'的有效模板参数,因为'static constexpr void main():::: _ FUN( )'没有联系

clang:

prog.cc:7:8:注意:非constexpr函数'operator void(*)()'不能用于常量表达式

c++ lambda language-lawyer constexpr

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

consitexpr构造函数在GCC编译时进行评估时给出不同的结果

构造函数使用一个函数来获取引用并按值返回,同时重复修改数据成员:

constexpr int   vv(int   x) {return x;}
constexpr int & rr(int & x) {return x;}
constexpr int   rv(int & x) {return x;}

constexpr struct S {
    int x {0};
    template<typename F> constexpr S(F f) {x = f(x) + 1; x = f(x) + 1;}
} s(rv); // s.x is 1 if function rv is used, 2 otherwise.
static_assert(s.x == 2, "");
Run Code Online (Sandbox Code Playgroud)

它只是rv在构造函数中使用时产生意外结果的函数.如果vv或者rr被传递,那么s.x就像预期的那样是2.

我注意到GCC 5.4.1 ARM上的行为,并且它似乎在支持C++ 14的所有GCC版本中都是相同的.Clang在所有情况下都给出了2的预期结果.GCC和Clang都没有启用Wall和Wextra的任何警告.

这个例子是有效的C++ 14和GCC中的错误吗?我阅读了标准中对常量表达式的限制列表,看不出任何明显的违反,但我不确定我是否理解所有技术细节.

c++ gcc g++ constexpr c++14

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

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

我可以在编译时检测"函数参数" 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
查看次数

为什么在编译时无法获得模板函数的参数计数?

#include <cstddef>

template<typename... Types>
constexpr std::size_t getArgCount(Types&&...) noexcept
{
    return sizeof...(Types);
}

struct A
{
    int n;

    void f()
    {
        static_assert(getArgCount(n) > 0); // not ok, why?
    }
};

int main()
{
    int n;
    static_assert(getArgCount(n) > 0); // ok
}
Run Code Online (Sandbox Code Playgroud)

为什么在编译时无法获得模板函数的参数计数?

错误信息:

1>test.cpp
1>test.cpp(17,45): error C2131:  expression did not evaluate to a constant
1>test.cpp(17,42): message :  failure was caused by a read of a variable outside its lifetime
1>test.cpp(17,42): message :  see usage of 'this'
Run Code Online (Sandbox Code Playgroud)

c++ static-assert language-lawyer constexpr c++11

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

如果可用,是否可以使用 std::endian ,否则做其他事情?

从 C++20 开始,我们可以有:

constexpr bool is_little_endian = std::endian::native == std::endian::little;
Run Code Online (Sandbox Code Playgroud)

如果可用,我希望有执行此操作的代码,否则执行运行时检测。这可能吗?

也许代码看起来像:

template<bool b = std_endian_exists_v> constexpr bool is_little_endian;
template<> constexpr bool is_little_endian<true> = std::endian::native == std::endian::little;
template<> constexpr bool is_little_endian<false> = runtime_detection();
Run Code Online (Sandbox Code Playgroud)

我知道__cplusplus通过预处理器进行测试是可能的,但是 C++20 中的编译器阶段在各个阶段都支持,因此这在任一方向都不是可靠的指标。

c++ endianness constexpr c++20

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