标签: if-constexpr

在lambda内部捕获的Constexpr变量失去了其解释性

这段代码可以在g ++(coliru)中很好地编译,但是在MSVC(Godbolt和我的VS2017)中却不能。

#include <type_traits>
#include <iostream>
template<class T> void f(){
    constexpr bool b=std::is_same_v<T,int>; //#1
    auto func_x=[&](){
        if constexpr(b){ //#error
        }else{
        }
    };
    func_x();
}
int main(){
    f<int>();
}
Run Code Online (Sandbox Code Playgroud)

(6):错误C2131:表达式未求值为常数
(6):注意:失败是由于在其生命周期之外读取变量导致的
(6):注意:请参见'this'的用法

哪一个(g ++或MSVC)错了?“ 请参阅'this'的用法
是什么??this

在保留编译时保证的同时如何解决呢?

在我的真实情况下,b (#1)一个复杂的语句取决于其他一些constexpr变量。

c++ lambda language-lawyer c++17 if-constexpr

19
推荐指数
2
解决办法
867
查看次数

std :: is_constant_evaluated行为

GCC9已经实施std::is_constant_evaluated.我玩了一点,我意识到这有点棘手.这是我的测试:

constexpr int Fn1()
{
  if constexpr (std::is_constant_evaluated())
    return 0;
  else
    return 1;
}

constexpr int Fn2()
{
  if (std::is_constant_evaluated())
    return 0;
  else
    return 1;
}

int main()
{
  constexpr int test1 = Fn1(); // Evaluates to 0
  int test2 = Fn1();           // Evaluates to 0
  int const test3 = Fn1();     // Evaluates to 0

  constexpr int test4 = Fn2(); // Evaluates to 0
  int test5 = Fn2();           // Evaluates to 1
  int const test6 = Fn2();     // …
Run Code Online (Sandbox Code Playgroud)

c++ constexpr c++20 if-constexpr

17
推荐指数
2
解决办法
692
查看次数

如果constexpr在递归泛型lambda中:不同的编译器行为

以下代码使用g ++ 7.3.0成功编译,无法使用clang ++ 6.0.0进行编译(编译标志为-std=c++17 -Wall -Wextra -Werror -pedantic-errors):

auto foo = [](auto, auto... tail) {
    if constexpr (sizeof...(tail) > 0)
    {
        return foo(tail...);
    }
    else
    {
        return 42;
    }
};

int main()
{
}
Run Code Online (Sandbox Code Playgroud)

clang ++编译错误信息:

错误:使用推导类型'auto'声明的变量'foo'不能出现在自己的初始化程序中

return foo(tail...);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,符合标准的行为是什么?

c++ lambda language-lawyer c++17 if-constexpr

15
推荐指数
1
解决办法
289
查看次数

if constexpr - 为什么完全检查丢弃的语句?

我在 GCC 10 中使用 c++20 consteval 并编写了这段代码

#include <optional>
#include <tuple>
#include <iostream>

template <std::size_t N, typename Predicate, typename Tuple>
consteval std::optional<std::size_t> find_if_impl(Predicate&& pred,
                                                  Tuple&& t) noexcept {
  constexpr std::size_t I = std::tuple_size_v<std::decay_t<decltype(t)>> - N;

  if constexpr (N == 0u) {
    return std::nullopt;
  } else {
    return pred(std::get<I>(t))
               ? std::make_optional(I)
               : find_if_impl<N - 1u>(std::forward<decltype(pred)>(pred),
                                      std::forward<decltype(t)>(t));
  }
}

template <typename Predicate, typename Tuple>
consteval std::optional<std::size_t> find_if(Predicate&& pred,
                                             Tuple&& t) noexcept {
  return find_if_impl<std::tuple_size_v<std::decay_t<decltype(t)>>>(
      std::forward<decltype(pred)>(pred), std::forward<decltype(t)>(t));
}

constexpr auto is_integral = [](auto&& …
Run Code Online (Sandbox Code Playgroud)

c++ c++20 if-constexpr

13
推荐指数
1
解决办法
708
查看次数

像"if constexpr"之类的东西,但是用于类定义

if constexpr是在C++程序中摆脱预处理器的重要一步.但它仅适用于函数 - 如下例所示:

enum class OS
{
    Linux,
    MacOs,
    MsWindows,
    Unknown
};

#if defined(__APPLE__)
constexpr OS os = OS::MacOs;
#elif defined(__MINGW32__)
constexpr OS os = OS::MsWindows;
#elif defined(__linux__)
constexpr OS os = OS::Linux;
#else
constexpr OS os = OS::Unknown;
#endif

void printSystem()    
{
    if constexpr (os == OS::Linux)
    {
        std::cout << "Linux";
    }
    else if constexpr (os == OS::MacOs)
    {
        std::cout << "MacOS";
    }
    else if constexpr (os == OS::MsWindows)
    {
        std::cout << "MS Windows";
    }
    else
    { …
Run Code Online (Sandbox Code Playgroud)

c++ class c-preprocessor c++17 if-constexpr

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

仍在评估废弃分支中的嵌套constexpr-if语句?

在我看来,在MSVC(版本15.7.3)中评估另一个constexpr-if语句的废弃分支内的constexpr-if语句.

请考虑以下代码:

#include <tuple>
#include <type_traits>

template <size_t I>
int test() {
    if constexpr(I != 0) {
        return 0;
    }
    else { // This branch is discarded, but it seems that the constexpr-if below is still evaulated?
        if constexpr(std::is_same_v<int, std::tuple_element_t<I, std::tuple<int>>>) { // some constexpr check that is valid only when I == 0
            return 1;
        }
        else {
            return 2;
        }
    }
}

int main() {
    test<1>();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

上面的代码无法在MSVC中编译,因为std::tuple_element_tI超过元组的边界时,静态断言将失败.这表明,不管怎样,废弃分支中的代码也会被评估,即使它依赖于模板参数I.

根据cppreference …

c++ nested c++17 if-constexpr

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

如果constexpr没有丢弃在模板化的lambda中的假分支

我在模板化的lambda中遇到"if constexpr"的问题.为了论证,让我们忽略我是如何到达那里的,但我有一个结构foo,它以某种方式定义,产生如下内容:

template<bool condition>
struct foo {
    int a;

    // Only contains b if condition is true
    int b;
}
Run Code Online (Sandbox Code Playgroud)

现在我可以定义一个模板函数thtemplate

template<bool condition>
void print_fun(foo & obj) {
    /* Do something with obj.a */
    if constexpr(condition)
        /* Do something with obj.b */
};
Run Code Online (Sandbox Code Playgroud)

实例化这个功能,并使用它会编译,如果constexpr参数foo是一样的一个print_fun,即

constexpr bool no = false;
foo<no> obj = {};
print_fun<no>(obj);
Run Code Online (Sandbox Code Playgroud)

这会编译,因为假分支在模板化实体内被丢弃,因此在print_fun中使用obj.b没有问题.

但是,如果我定义一个类似的lambda表达式如下:

template<bool condition>
auto print_lambda = [](foo & obj) {
    /* Do something with obj.a */
    if constexpr(condition)
        /* Do something …
Run Code Online (Sandbox Code Playgroud)

c++ lambda templates c++17 if-constexpr

10
推荐指数
1
解决办法
796
查看次数

如果为false,则不会编译std :: is_member_function_pointer

我正在寻找的是:我有一个模板化的类,如果该类具有所需的函数,则想调用一个函数,例如:

template<class T> do_something() {
    if constexpr (std::is_member_function_pointer<decltype(&T::x)>::value) {
        this->_t->x(); // _t is type of T*
    }
}
Run Code Online (Sandbox Code Playgroud)

发生的情况:如果T不带功能,则编译器不会编译。小例子:

#include <type_traits>
#include <iostream>

class Foo {
public:
    void x() { }
};

class Bar { };

int main() {
    std::cout << "Foo = " << std::is_member_function_pointer<decltype(&Foo::x)>::value << std::endl;
    std::cout << "Bar = " << std::is_member_function_pointer<decltype(&Bar::x)>::value << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译器说:

is_member_function_pointer.cpp:17:69: error: no member named 'x' in 'Bar'; did you mean 'Foo::x'?
    std::cout << "Bar …
Run Code Online (Sandbox Code Playgroud)

c++ type-traits if-constexpr

10
推荐指数
1
解决办法
265
查看次数

如何正确使用概念?

目前,我正在学习 C++,并决定从 C++20 开始。然而,这些代码让我发疯,因为我认为结果没有任何意义。

以下代码将Valid array.打印句子。我上面的意思是,这是不对的。它根本不应该打印句子,因为我在参数中插入的类型与概念不匹配。

在 VS2022 Preview 3 和具有最新 GCC 和 C++2A(GNU) 参数的在线编译器上进行测试,生成了相同的结果。

#include <array>
#include <cstdio>
#include <iostream>
#include <type_traits>

using namespace std;

template<typename A> concept ProperArray = requires(A array)
{
    {array.max_size() >= 2U};
    {std::is_arithmetic_v<typename A::value_type> == true};
};

int main()
{
    constexpr bool b = ProperArray<array<std::string, 1>>;
    if constexpr (b)
        cout << "Valid array." << endl;
        
    std::cout << "Hello, Wandbox!" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

c++ c++-concepts c++20 if-constexpr

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

为什么constexpr需要其他工作?

我试图以if constexpr下列方式使用:

template<template <typename First, typename Second> class Trait,
    typename First, typename Second, typename... Rest>
constexpr bool binaryTraitAre_impl()
{
    if constexpr (sizeof... (Rest) == 0)
    {
        return Trait<First, Second>{}();    
    }
    return Trait<First, Second>{}() and binaryTraitAre_impl<Trait, Rest...>();
}
Run Code Online (Sandbox Code Playgroud)

用例示例:

static_assert(binaryTraitAre_impl<std::is_convertible,
    int, int&,
    int*, void*>());
Run Code Online (Sandbox Code Playgroud)

但这无法编译

clang:

error: no matching function for call to 'binaryTraitAre_impl'
        return Trait<First, Second>{}() and binaryTraitAre_impl<Trait, Rest...>();
                                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

gcc:

prog.cc: In instantiation of 'constexpr bool binaryTraitAre_impl() [with Trait = std::is_convertible; First = int*; Second …
Run Code Online (Sandbox Code Playgroud)

c++ templates template-meta-programming c++17 if-constexpr

9
推荐指数
2
解决办法
448
查看次数