C++ テンプレートで条件付きコードのインスタンス化を行う最もクリーンな方法 質問する

C++ テンプレートで条件付きコードのインスタンス化を行う最もクリーンな方法 質問する

次の 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;
}

本質的には、テンプレートパラメータに応じて特定の操作が実行されるテンプレートクラスAを実装したいのです。これらの操作にはローカル変数が必要で、必要な場合にのみ割り当てたいのです。ここで問題となるのは、

if (hasdata) {
    data.setData(3);
}

条件は hasdata=false に対してもインスタンス化されますが、これはコンパイルされません (g++ 5.2 を使用)。A::A() の本体を分割せずに、これを最もクリーンな方法で実行する方法について何かアイデアはありますか?

上記のソース コードは、最小限の動作しない例です。A::A() の実際の実装は比較的長く、"hasdata" に依存する部分はコード全体に均等に分散されています。また、クラス A が使用される "typename T" は、重いコンストラクタ/デストラクタを持つ比較的複雑なクラスであるため、T のインスタンスは hasdata=true の場合にのみ割り当てられるようにします。最後に、data.setData(...) 呼び出しでは、"..." に複雑な計算が行われる可能性があります。これは必要な場合にのみ実行する必要があります。

ベストアンサー1

もし余裕があれば、条件分岐を汎用ラムダとして表現できます。その利点は、周囲の変数をキャプチャし、ソリューションに追加のメンバー関数を必要としないことです。

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);

デモ

こう言うこともできます:

if constexpr (hasdata)
{
    data.setData(3);
}

デモ2

おすすめ記事