例如:
void foo()
{
if constexpr (...)
int x = 5;
else
double x = 10.0;
bar(x); // calls different overloads of bar with different values
}
Run Code Online (Sandbox Code Playgroud)
这是D lang的常见情况,但我没有找到有关C++ 17的信息.
当然,可以使用类似的东西
std::conditional<..., int, double>::type x;
Run Code Online (Sandbox Code Playgroud)
但仅限于基本情况.即使是不同的初始化者(如上所述)也会产生很大的问题.
static_assert
在 的 false 分支中应丢弃以下内容if constexpr
,但由于断言失败而导致编译失败:
#include <type_traits>
template <class T>
constexpr bool f() {
if constexpr (std::is_same<T, int>::value) return true;
else static_assert(false, "message");
}
int main () {
if constexpr (f<int>()) return 1;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我希望丢弃的分支if constexpr
不会被评估,因为它f
是用 type 实例化的int
。
用 Gcc 7.2 (-std=c++17) 编译
我有一个问题,我几乎可以肯定是一个MSVC错误,但也许我错过了一些东西.
这是实际代码的简化版本:
template <typename... Args>
class InnerType {};
template <typename... Args>
class OuterType {
public:
void foo1() {
if constexpr (true) {
bar(InnerType<Args...>());
}
}
void foo2() {
if (true) {
bar(InnerType<Args...>());
}
}
void bar(InnerType<Args...>) {}
};
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,唯一的区别foo1()
和foo2()
是constexpr如果.当我尝试在MSVC中编译一些测试时会发生以下情况:
OuterType<const bool> test1;
test1.foo1(); // does not compile
test1.foo2(); // compiles
OuterType<bool> test2;
test2.foo1(); // compiles
test2.foo2(); // compiles
Run Code Online (Sandbox Code Playgroud)
我得到的错误test1.foo1()
是:
error C2664: 'void OuterType<const bool>::bar(InnerType<const bool>)':
cannot convert argument 1 from 'InnerType<bool>' to 'InnerType<const bool>' …
Run Code Online (Sandbox Code Playgroud) 我正在经历Herb Scutter的
旅程:走向更强大,更简单的C++编程
结构绑定部分
为了理解这个概念.Best是编写一个我试过的程序,但是遇到了一些错误
只是想尝试如何在类上使用私有数据的结构绑定.请忽略下面的示例.如果您能提供任何示例
#include<iostream>
#include<string>
using namespace std;
class foobar {
public:
foobar() { cout << "foobar::foobar()\n"; }
~foobar() { cout << "foobar::~foobar()\n"; }
foobar( const foobar &rhs )
{ cout << "foobar::foobar( const foobar & )\n"; }
void ival( int nval, string new_string ) { _ival = nval;s=new_string; }
private:
int _ival;
string s;
};
foobar f( int val,string new_string ) {
foobar local;
local.ival( val,new_string );
return local;
}
template<> struct tuple_element<0,foobar> { using …
Run Code Online (Sandbox Code Playgroud) 我声称这个程序应该是格式良好的:它声明了一个constexpr成员函数S<int>
.但是,GCC和Clang都拒绝接受这个计划.
template<class T>
struct S {
constexpr int foo() {
if constexpr (std::is_same_v<T, int>) {
return 0;
} else {
try {} catch (...) {}
return 1;
}
}
};
int main()
{
S<int> s;
return s.foo(); // expect "return 0"
}
Run Code Online (Sandbox Code Playgroud)
GCC说:
错误:'constexpr'功能'尝试'
Clang说:
错误:constexpr函数中不允许使用语句
他们似乎都没有注意到"try"语句位于语句的废弃分支中if constexpr
.
如果我将try
/ catch
out分解为非constexpr成员函数void trycatch()
,那么Clang和GCC都会再次对代码感到满意,即使它的行为应该等同于不满意的版本.
template<class T>
struct S {
void trycatch() {
try {} catch (...) {}
}
constexpr int …
Run Code Online (Sandbox Code Playgroud) 我想if constexpr
完全理解.
我理解,如果if constexpr(expr)
在模板中使用,并且expr
依赖于模板参数,那么在实例化期间,只有一个then
/ else
分支将被实例化,另一个将被丢弃.
我有两个问题:
expr
不依赖于模板参数,那么if constexpr(expr)
将不会丢弃任何分支?如果是,标准在哪里这样说?我没有看到标准有什么例外,丢弃只在expr
依赖时发生.if constexpr
模板以外有用吗?如果是,这有什么用例?你能举出一些例子来了解它的用处吗?我昨天读了几个关于在an 子句中使用的答案。我知道根据标准,它被认为是格式错误的(即使某些编译器,包括 MSVC2017,会接受它)。Qt 也会将此标记为错误。static_assert(false, "Some message")
else
if constexpr
我的问题是,下面的代码是否符合标准?(我倾向于这么认为,但我想确认一下。)
template <typename TypeOfValue>
static void PushValue(duk_context* ctx, TypeOfValue value) {
// Push value onto duktape stack
if constexpr (std::is_same<TypeOfValue, int>::value) {
// Push int
duk_push_int(ctx, value);
} else if constexpr (std::is_same<TypeOfValue, uint32_t>::value) {
// Push uint
duk_push_uint(ctx, value);
} else {
// Unsupported type
static_assert(bool_value<false, TypeOfValue>(), "Unsupported type");
}
}
template <bool value, typename T>
static constexpr bool bool_value() {return value;}
Run Code Online (Sandbox Code Playgroud)
编辑: …
我想e
在编译时计算价值(不用担心,不是作业),但出了点问题.
template<size_t limit = 3, class result = std::ratio<0, 1>, size_t factorial = 1, size_t count = 1>
constexpr double e_impl() {
if constexpr(limit == 0) {
return static_cast<double>(result{}.num) / result{}.den;
}
return e_impl<limit - 1, std::ratio_add<result, std::ratio<1, factorial>>, factorial * count, count + 1>();
}
Run Code Online (Sandbox Code Playgroud)
虽然计算值是正确的,但编译器会抛出有关模板溢出的错误.似乎limit
变量超出范围(下面0
),但它不应该发生,因为0
-case由if constexpr(…)
语句处理.
所以问题是,我错了,应该预期这种行为,还是编译错误?用GCC 7.1.0编译.
如果您有一个if constexpr ()
决定做一件事或另一件事的函数,那么在一种情况下如何返回左值,在另一种情况下如何返回右值?
以下示例不会在第一个用法行中编译,因为返回类型auto
为无引用:
static int number = 15;
template<bool getref>
auto get_number(int sometemporary)
{
if constexpr(getref)
{
return number; // we want to return a reference here
}
else
{
(...) // do some calculations with `sometemporary`
return sometemporary;
}
}
void use()
{
int& ref = get_number<true>(1234);
int noref = get_number<false>(1234);
}
Run Code Online (Sandbox Code Playgroud) 考虑以下代码。如果我的理解if constexpr
是正确的,则else
不应编译分支,因此z()
不应将其视为错误。
#include <type_traits>
struct Z{};
template<typename T>
void f(T z) {
auto lam = [z]() {
if constexpr(std::is_same<T, Z>::value) {
} else {
z();
}
};
}
int main() {
f(Z{});
}
Run Code Online (Sandbox Code Playgroud)
用clang和gcc编译;但是使用最新的MSVC却没有。不幸的是,goldbolt的MSVC太旧了,但是在我的计算机上使用VS 2017进行了全面更新,结果是cl /std:c++17
:
Microsoft (R) C/C++ Optimizing Compiler Version 19.14.26428.1 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
if_constexpr.cpp
if_constexpr.cpp(10): error C2064: term does not evaluate to a function taking 0 arguments
if_constexpr.cpp(16): note: …
Run Code Online (Sandbox Code Playgroud)