MSVCでクラステンプレート内変数テンプレートのバグ?


std::enable_if<~~, std::nullptr_t> = nullptr ってクッソ長いよね

テンプレートパラメータ内でenable_ifを使うとき、enable_ifの条件文が長ったらしくなることがあった(ついでに複数ヶ所で同条件があった)のでクラス内変数テンプレートでまとめてみた...

こんな感じ
#include <type_traits>

template <int x>
struct A {
    template <int y>
    static constexpr bool flag = x < y;

    template <int y, std::enable_if_t<flag<y>, std::nullptr_t> = nullptr>
    void f() {
    }
};

int main() {
    A<1> a;
    a.f<2>();
    return 0;
}

...ら このコード、MSVCではビルドできない
xのライフタイムが期限切れとか言われる

GCC https://godbolt.org/z/s8o1jP
Clan https://godbolt.org/z/dCu8gg
MSVC https://godbolt.org/z/NO5Ofl

wandboxさんMSVC使えるようにならないかな...

対処

MSVCを使わない

一応、回避方法はあった

  • テンプレートパラメータ内で変数テンプレートを使うのをやめる
    • enable_ifを戻り値などで使う
  • 変数テンプレートではなく、クラス内にメタ関数みたいなクラスを作ってその中で変数宣言する
#include <type_traits>

template <int x>
struct A {
    template <int y>
    static constexpr bool flag = x < y;

    // template <int y, std::enable_if_t<flag<y>, std::nullptr_t> = nullptr>
    // void f() {
    // }

    template <int y>
    auto g() -> std::enable_if_t<flag<y>> {
    }

    template <int y>
    struct Hoge{
        static constexpr bool value = x < y;
    };

    template <int y, std::enable_if_t<Hoge<y>::value, std::nullptr_t> = nullptr>
    void h() {
    }
};

int main() {
    A<1> a;
    // a.f<2>();
    a.g<2>();
    a.h<2>();
    return 0;
}

これならMSVCでもビルドできた
https://godbolt.org/z/CR25J-