C++模板中条件代码实例化的最简洁方法

DCT*_*Lib 18 c++ templates

我正在尝试运行以下C++代码:

#include <cmath>

template<typename T, bool> class ConditionalData {
};

template <typename T> class ConditionalData<T, false> {
};

template <typename T> class ConditionalData<T, true> {
private:
    T data;
public:
    void setData(T _data) { data = _data; }
};


template<bool hasdata> class A {
public:
    A() {
        ConditionalData<double,hasdata> data;
        if (hasdata) {
            data.setData(sin(cos(123.4)));
        }
    }
};


int main(int argNum, const char**argData) {
    A<false> test1;
    A<true> test2;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

本质上,我想实现一个模板化的类A,其中根据模板参数执行某些操作.这些操作需要局部变量,我只想在需要时分配它们.我在这里遇到的问题是身体的问题

if (hasdata) {
    data.setData(3);
}
Run Code Online (Sandbox Code Playgroud)

条件也是为hasdata = false实例化的,它不能编译(使用g ++ 5.2).任何想法如何以最干净的方式完成这项工作而不将A :: A()的主体分成几部分?

上面的源代码是一个最小的非工作示例.A :: A()的实际实现相对较长,依赖于"hasdata"的部分均匀分布在代码上.此外,将使用类A的"typename T"是具有重量级构造函数/析构函数的相对复杂的类,因此我希望仅在hasdata = true时分配T的实例.最后,在data.setData(...)调用中,"..."中可能存在复杂的计算,只有在需要时才应执行.

Pio*_*cki 13

如果你能负担得起,你可以将条件分支表示为通用lambdas.好处是它们捕获周围的变量,解决方案不需要额外的成员函数.

template <bool> struct tag {};

template <typename T, typename F>
auto static_if(tag<true>, T t, F f) { return t; }

template <typename T, typename F>
auto static_if(tag<false>, T t, F f) { return f; }

template <bool B, typename T, typename F>
auto static_if(T t, F f) { return static_if(tag<B>{}, t, f); }

template <bool B, typename T>
auto static_if(T t) { return static_if(tag<B>{}, t, [](auto&&...){}); }

// ...

ConditionalData<int, hasdata> data;        
static_if<hasdata>([&](auto& d)
{
    d.setData(3);
})(data);
Run Code Online (Sandbox Code Playgroud)

DEMO

你可以说:

if constexpr (hasdata)
{
    data.setData(3);
}
Run Code Online (Sandbox Code Playgroud)

演示2


Tar*_*ama 7

这是一种常见的模式,因此实际上有一篇文章要添加constexpr_if到C++中.如果它适用于未来版本,它将允许您保持代码非常原样.

template<bool hasdata> class A {
public:
    A() {
        ConditionalData<int,hasdata> data;
        constexpr_if (hasdata) {
        //^^^^^^^^^^ instead of plain if
            data.setData(3);
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

目前,您需要处理其他一个答案.


编辑:这被添加到C++ 17并被调用 if constexpr


iam*_*ind 5

首先,您不需要3个版本class ConditionalData,因为bool可以是true或者false.所以让我简化如下:

template<typename T, bool = false> class ConditionalData {
};                 //^^^^^^^^^^^^

template <typename T> class ConditionalData<T, true> {
private:
    T data;
public:
    void setData(T _data) { data = _data; }
};
Run Code Online (Sandbox Code Playgroud)

其次,回答你的问题:无论哪个成员属于false类别,只需将它们超出class身体,如下所示:

template<bool hasdata> class A { 
public:
    A() {
        ConditionalData<int,hasdata> data;
        if (hasdata) {
            data.setData(3);
        }
    }   
};

template<> A<false>::A() {}  // Does nothing for `false` condition
Run Code Online (Sandbox Code Playgroud)