if/else在C++的编译时?

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)


Bo *_*son 5

您可以为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)


Cir*_*四事件 5

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)

GitHub上游

编译并运行:

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中进行了测试。