Vin*_*ent 14 c++ templates if-statement compilation
请考虑以下代码:
#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;
}
Run Code Online (Sandbox Code Playgroud)
对于x(非常量),没有问题.但是,即使在编译时知道if/else中的条件,y(const数据类型)也会导致错误.
是否有可能在编译时不编译错误条件?
eca*_*mur 11
最简单的修复是部分模板专业化:
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; }
};
Run Code Online (Sandbox Code Playgroud)
另一种选择是授权:
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; }
};
Run Code Online (Sandbox Code Playgroud)
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;
};
Run Code Online (Sandbox Code Playgroud)
您可以为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
};
Run Code Online (Sandbox Code Playgroud)
C ++ 17 if constexpr
哦,是的,它已经到达:
main.cpp
#include <cassert>
#include <type_traits>
template <class T>
struct MyClass {
int myFunc() {
if constexpr(std::is_integral<T>())
return 1;
else
return 2;
}
};
int main() {
assert(MyClass<int>().myFunc() == 1);
assert(MyClass<float>().myFunc() == 2);
}
Run Code Online (Sandbox Code Playgroud)
编译并运行:
g++-8 -std=c++17 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
Run Code Online (Sandbox Code Playgroud)
另请参见:“ if constexpr()”与“ if()”之间的区别
与C ++ 20“字符串文字模板参数”一起使用时,这真的很酷:将字符串文字作为参数传递给C ++模板类
在Ubuntu 16.04,GCC 8.1.0中进行了测试。