if / else at compile time in C++?
if / else at compile time in C++?
考虑以下代码:
#include <iostream>
#include <type_traits>
template<typename T> class MyClass
{
public:
MyClass() : myVar{0} {;}
void testIf() {
if (isconst) {
myVar;
} else {
myVar = 3;
}
}
void testTernary() {
(isconst) ? (myVar) : (myVar = 3);
}
protected:
static const bool isconst = std::is_const<T>::value;
T myVar;
};
int main()
{
MyClass<double> x;
MyClass<const double> y;
x.testIf();
x.testTernary();
y.testIf(); // <- ERROR
y.testTernary(); // <- ERROR
return 0;
}
对于x(非常数)没有问题。但是,即使在编译时if/else中的条件已知,y(const数据类型)也会导致错误。
是否有可能在编译时不编译false条件?
C++17 if constexpr
哦,是的,它已经到了:
main.cpp
#include <cassert>
#include <type_traits>
template<typename T>
class MyClass {
public:
MyClass() : myVar{0} {}
void modifyIfNotConst() {
if constexpr(!isconst) {
myVar = 1;
}
}
T myVar;
protected:
static constexpr bool isconst = std::is_const<T>::value;
};
int main() {
MyClass<double> x;
MyClass<const double> y;
x.modifyIfNotConst();
y.modifyIfNotConst();
assert(x.myVar == 1);
assert(y.myVar == 0);
return 0;
}
GitHub上游。
编译并运行:
g++-8 -std=c++17 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
另见";如果constexpr()"Vs";如果()"
这与C++20"字符串文本模板参数"一起将非常酷:将字符串文本作为参数传递给C++模板类
在Ubuntu 16.04,GCC 8.1.0中测试。
最简单的修复方法是部分模板专用化:
template<typename T> class MyClassBase
{
public:
MyClassBase() : myVar{0} {;}
protected:
T myVar;
};
template<typename T> class MyClass: MyClassBase<T>
{
public:
void testIf() { myVar = 3; }
};
template<typename T> class MyClass<const T>: MyClassBase<const T>
{
public:
void testIf() { myVar; }
};
另一种选择是授权:
template<typename T> class MyClass
{
public:
MyClass() : myVar{0} {;}
void testIf() { testIf_impl(std::integral_constant<bool, isconst>()); }
protected:
static const bool isconst = std::is_const<T>::value;
T myVar;
private:
void testIf_impl(std::true_type) { myvar; }
void testIf_impl(std::false_type) { myVar = 3; }
};
SFINAE是另一种选择,但通常不适合这种情况:
template<typename T> class MyClass
{
public:
MyClass() : myVar{0} {;}
template
<typename U = void>
typename std::enable_if<std::is_const<T>::value, U>::type testIf() { myvar; }
template
<typename U = void>
typename std::enable_if<!std::is_const<T>::value, U>::type testIf() { myvar = 3; }
protected:
static const bool isconst = std::is_const<T>::value;
T myVar;
};
您可以将类专门化为const类型
template<typename T>
class MyClass
{
// Whatever you need to do
};
template<typename T>
class MyClass<const T>
{
// Whatever you need to do for const types
};
为给定类型编译类模板。即使控制流没有到达赋值,也会编译该赋值。由于成员是const,因此编译将失败。
你可以使用某种形式的SFINAE来跳过这项任务,但它不会像现在这样起作用。
这很有效(为了简单起见,我删除了testTernary
成员函数):
#include <iostream>
#include <type_traits>
template<typename T> class MyClass
{
public:
MyClass() : myVar{0} {;}
template<class U = T>
typename std::enable_if<std::is_const<U>::value>::type testIf() {
myVar;
}
template<class U = T>
typename std::enable_if<!std::is_const<U>::value>::type testIf() {
myVar = 3;
}
protected:
static const bool isconst = std::is_const<T>::value;
T myVar;
};
int main()
{
MyClass<double> x;
MyClass<const double> y;
x.testIf();
y.testIf();
return 0;
}
如果没有编译else分支,那么您的函数将具有完全不同的含义。你不能只是不编译部分代码。如果你不想让它执行,就不要写它。这不像每次调用函数都要单独编译。
类型系统的全部目的是避免意外地尝试执行诸如分配给const
变量之类的操作。您必须编写一个全新的(或重载的)函数,该函数不分配给该变量。
试试这个:
template<typename T>
class MyClass
{
T myVar;
public:
MyClass() : myVar(0) {}
void testIf()
{
assign(myVar, 3);
}
private:
template<typename V>
void assign(V& destination, int value)
{
destination = value;
}
template<typename V>
void assign(const V& destination, int value)
{
}
};
相关文章:
- netcat command in c++
- Difference in displaying cv2 Mat
- C++ MFC Libraries in Travis CI
- 如何在OpenSSL中从configuration.h.in获取configuration.h
- 创建具有 new in 函数和"this is nullptr"异常的对象
- IN, OUT, INOUT Parameters
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- 有人安装"IITB Simplecpp in mac"吗?
- 从 C 样式字符串中删除子字符串 "in place" 在C++代码中
- 如何修复"error: ‘_1’ was not declared in this scope"?
- Softmax Implementation in C++
- 将 out/in out 参数与 if/switch 的 init 语句一起使用
- IF-nesting in c++
- Gurobi GRBModel and GRBmodel in C++
- Tensorflow Hub in C++
- Centos7 g++ "to_string is not in a member of std"
- InitializeCriticalSectionEx Not Located In KERNEL32.Dll
- 将 lambda 表达式传递给 std::function in C++
- @CPPFLAGS@在 Makefile.in 中意味着什么?
- std::async from std::async in windows xp