26553


下記のような実装を持たない関数プロトタイプがあるとします。

[code]

    struct tag1{};
    struct tag2{};
    
    // function declaration
    std::true_type has_hoge(tag1);
    std::false_type has_hoge(tag2);
    
[/code]

また、下記のようなboolの型がtrueの場合は整数型を符号ありに、falseの場合は整数型の符号を外すconvertクラスを考えます。

[code]

    template<bool cond, typename  int_type>
    struct convert;
    
    template<typename  int_type>
    struct convert<true, int_type>
    {
        typedef typename  std::make_signed<int_type>::type type;
    };
    
    template<typename  int_type>
    struct convert<false, int_type>
    {
        typedef typename  std::make_unsigned<int_type>::type type;
    };
    
[/code]

このconvertとhas_hogeのtag dispatchを用いると下記のように書くことができます。

[code]

    // int
    convert<decltype(has_hoge(tag1()))::type::value, int>::type int_hoge;
    
    // unsigned int
    convert<decltype(has_hoge(tag2()))::type::value, int>::type uint_hoge;
    
[/code]

このtag1およびtag2の部分をテンプレートにしたいのですが、エラーとなってしまいます。

[code]

    /* コンパイルエラーになる。
    template<typename tag, typename int_type>
    struct hogehoge
    {
        typedef typename convert<decltype(has_hoge(tag()))::type::value, int_type>::type type;
    };
    */
    
[/code]

テンプレートはテンプレート引数が与えられるまでは実態化されないため、上記のコードは問題ないと思うのですがエラーとなります。

どのようにしたらエラーを回避できるでしょうか？

環境はvisual studio 2015 professionalです。

追記

回答をいただいたworkaroundを追加した例です。

[code]

    #include<type_traits>
    #include<iostream>
    
    struct tag1{};
    struct tag2{};
    
    // function declaration
    static std::true_type has_hoge(tag1);
    static std::false_type has_hoge(tag2);
    
    template<bool cond, typename  int_type>
    struct convert;
    
    template<typename  int_type>
    struct convert<true, int_type>
    {
        typedef typename  std::make_signed<int_type>::type type;
    };
    
    template<typename  int_type>
    struct convert<false, int_type>
    {
        typedef typename  std::make_unsigned<int_type>::type type;
    };
    
    template<typename tag, typename int_type>
    struct result
    {
    private:
        typedef typename decltype(has_hoge(tag())) _type;
    public:
        typedef typename convert<_type::type::value, int_type>::type type;
    };
    
    int main()
    {
        std::cout << typeid(result<tag1, int>::type).name() << std::endl;
        std::cout << typeid(result<tag2, int>::type).name() << std::endl;
    
        return 0;
    }
    
[/code]


CC BY-SA 3.0
2016-06-07T15:32:52.350
26546
2016-06-08T12:08:57.893
2016-06-08T12:08:57.893
question
c++ templates
テンプレートパラメータをタグディスパッチの入力として用いてメタプログラミングを実現する方法？


gcc 6.1ではコンパイル可能なようです。  
[ideone](http://ideone.com/cl50EV)のC++14でもいけますね。

VS2015の挙動はバグっぽい感じです。  
回避策として、以下のように型定義を分割すればいけるっぽいです。

[code]

    template<typename tag, typename int_type>
    struct hogehoge
    {
    private:
        typedef decltype(has_hoge(tag())) t_;
    
    public:
        typedef typename convert<t_::type::value, int_type>::type type;
    };
    
[/code]


CC BY-SA 3.0
2016-06-08T05:35:24.820
26553
2016-06-08T09:28:06.200
2016-06-08T09:28:06.200
4765
4765
26546
answer