Nagarei / DxLibEx

DXライブラリC++化プロジェクト
Boost Software License 1.0
31 stars 3 forks source link

VS2013でのDXLE_NOEXCEPT #29

Closed Nagarei closed 8 years ago

Nagarei commented 8 years ago

noexceptですが、どうもVS2013ではうまく認識してくれていないみたいです。

1>  calc_coordinate.cpp
1>c:\...\dxlibexproject\dxlibex\algorithm\safe_dist.hpp(14): warning C4346: 'std::is_arithmetic<T2>::value' : 依存名は型ではありません。
1>          'typename' を持つプレフィックスは型を示します。
1>c:\...\dxlibexproject\dxlibex\algorithm\safe_dist.hpp(14): error C3646: 'noexcept' : 不明なオーバーライド指定子です
1>c:\...\dxlibexproject\dxlibex\algorithm\safe_dist.hpp(14): error C2143: 構文エラー : ';' が '->' の前にありません。
1>c:\...\dxlibexproject\dxlibex\algorithm\safe_dist.hpp(14): error C3551: 後続の戻り値の型が必要です
1>c:\...\dxlibexproject\dxlibex\algorithm\safe_dist.hpp(14): error C2988: 認識できないテンプレートの宣言または定義です。
1>c:\...\dxlibexproject\dxlibex\algorithm\safe_dist.hpp(14): error C2059: 構文エラー : '->'
1>c:\...\dxlibexproject\dxlibex\algorithm\safe_dist.hpp(18): error C2143: 構文エラー : ';' が '}' の前にありません。
...
yumetodo commented 8 years ago

なんだって!? ・・・それは2013 November CTPのことでいいですか?2013そのものにはnoexceptないですし

あと、私2013消しちゃったので検証できないんですが、2013Update4と2013 November CTPの_MSC_FULL_VER ってなんでしたっけ。

yumetodo commented 8 years ago

焦ったけどTrailing return types(N2541)自体はVisual Studio 2010で実装されてるな。 https://msdn.microsoft.com/ja-jp/library/hh567368.aspx

Nagarei commented 8 years ago

僕のVS2013は_MSC_FULL_VERが180040629になってます。 これだとDXLE_NOEXCEPT_OR_NOT_THROWがnoexceptに展開さますが、どうもそれが原因でコンパイルエラーになっているようです。 たぶんvisualc.hppの

#if _MSC_FULL_VER < 180031101
#   define DXLE_NO_CXX11_NOEXCEPT
#endif

ここが間違っているのではないかと思います。 ただ自分に正確な知識がないので直せないという状況です。

yumetodo commented 8 years ago

Visual Studioのバージョンと判別マクロ

_MSC_VER _MSC_FULL_VER name
1500 150030729未満 Visual Studio 2008
1500 150030729 Visual Studio 2008 Update1
1600 160040219未満 Visual Studio 2010
1600 160040219 Visual Studio 2010 Update1
1700 170050727未満 Visual Studio 2012 Beta/RC/PR
1700 170051106 Visual Studio 2012 Update1
1700 170060315 Visual Studio 2012 Update2
1700 170060610 Visual Studio 2012 Update3
1700 170061030 Visual Studio 2012 Update4
1700 170051025 Visual Studio 2012 Nobemver CTP
1800 180021005未満 Visual Studio 2013 Preview/Beta/RC
1800 MSが馬鹿だったので書き換えなかった Visual Studio 2013 Update1
1800 180030501 Visual Studio 2013 Update2
1800 180030723 Visual Studio 2013 Update3
1800 180031101 Visual Studio 2013 Update4
1800 180040629 Visual Studio 2013 Update5
1800 180021114 Visual Studio 2013 Nobemver CTP
1900 190023026未満 Visual Studio 2015 Preview/Beta/RC
1900 190023026 Visual Studio 2015
1900 190023506 Visual Studio 2015 Update1
1900 190023824 Visual Studio 2015 Update2 RC

参考サイト

yumetodo commented 8 years ago

どうもNobemver CTPの判定をミスっていたようです。しっかし、Nobemver CTPだけなんで番号が変則的なんだ。

yumetodo commented 8 years ago

これでどうでしょうか?

auto f() throw() -> int;

という書き方が認められるなら通ると思うんですが。

Nagarei commented 8 years ago

とりあえず報告です。新しいエラーが二つ出てしまいました。

1>c:\...\dxlibexproject\dxlibex\basic_types\point2d.hpp(543): error C2995: 'dxle::point_c<T,default_valueAttribute> dxle::detail::abs_helper(const dxle::point_c<T,default_valueAttribute> &) throw()' : 関数テンプレートは既に定義されています
1>          c:\...\dxlibexproject\dxlibex\basic_types\point2d.hpp(541) : 'dxle::detail::abs_helper' の宣言を確認してください。
...
1>c:\...\dxlibexproject\samples\calc_coordinate\calc_coordinate\calc_coordinate.cpp(139): error C2664: 'std::pair<dxle::sizeui,dxle::sizeui>::pair(const std::pair<dxle::sizeui,dxle::sizeui> &) throw()' : 引数 2 を 'const dxle::size_c<const unsigned int,default_valueAttribute>' から 'const dxle::sizeui &' へ変換できません。
1>          理由: 'const dxle::size_c<const unsigned int,default_valueAttribute>' から 'const dxle::sizeui' へは変換できません。
1>          この変換を実行可能なユーザー定義変換演算子がないか、または演算子を呼び出せません。
yumetodo commented 8 years ago
1>c:\...\dxlibexproject\dxlibex\basic_types\point2d.hpp(543): error C2995: 'dxle::point_c<T,default_valueAttribute> dxle::detail::abs_helper(const dxle::point_c<T,default_valueAttribute> &) throw()' : 関数テンプレートは既に定義されています
1>          c:\...\dxlibexproject\dxlibex\basic_types\point2d.hpp(541) : 'dxle::detail::abs_helper' の宣言を確認してください。

これは原因が浮かばない・・・。

1>c:\...\dxlibexproject\samples\calc_coordinate\calc_coordinate\calc_coordinate.cpp(139): error C2664: 'std::pair<dxle::sizeui,dxle::sizeui>::pair(const std::pair<dxle::sizeui,dxle::sizeui> &) throw()' : 引数 2 を 'const dxle::size_c<const unsigned int,default_valueAttribute>' から 'const dxle::sizeui &' へ変換できません。
1>          理由: 'const dxle::size_c<const unsigned int,default_valueAttribute>' から 'const dxle::sizeui' へは変換できません。
1>          この変換を実行可能なユーザー定義変換演算子がないか、または演算子を呼び出せません。

これは139行目の

    return { s13, s14 };

    static_assert(std::is_same<decltype(s14)::value_type, unsigned int>::value, "error");
    return { s13, s14 };

にした結果を知りたいですね・・・

Nagarei commented 8 years ago

後者

    typedef decltype(s14) s14_t;
    static_assert(std::is_same<s14_t::value_type, unsigned int>::value, "error");
    static_assert(std::is_same<s14_t::value_type, const unsigned int>::value, "not const");
    static_assert(std::is_same<s14_t, dxle::size_c<decltype(s13.width * 2U)>>::value, "error2");

で試したところ、error``error2のみが表示されました。 なおIntelliSenseではs14はconst <error-type>になっています。

Nagarei commented 8 years ago

前者

    namespace detail{
        template<typename T>
        enable_if_t<std::is_signed<T>::value, point_c<T>> abs_helper(const point_c<T>& o) DXLE_NOEXCEPT_OR_NOTHROW{ return{ std::abs(o.x), std::abs(o.y) }; }
        template<typename T, enable_if_t<std::is_unsigned<T>::value, std::nullptr_t> = nullptr>
        point_c<T> abs_helper(const point_c<T>& o) DXLE_NOEXCEPT_OR_NOTHROW { return o; }
    }

これでとりあえずエラーは出なくなりました。何なんだいったい。

yumetodo commented 8 years ago

前者:もはや謎

後者

template<typename T1, typename T2> T1 f(const std::pair<T1, T1>& p, T2 n)
{
    static_assert(std::is_same<int, decltype(p.first + n)>::value, "is const");
    return n;
}
void g()
{
    const int n = 9;
    const auto p = std::make_pair(3, 1);
    f(p, n);
}

これってassertされましたっけ。されないはずなんですが・・・。

Nagarei commented 8 years ago

前者 上ので書き直して良いですか?汚くはなりますけど...。 後者 試したのはsize_c_sample関数の中なので普通にstatic_assertされるはずです。 72e0504 にした後も継続してエラーになっています。

yumetodo commented 8 years ago

上ので書き直して良いですか?汚くはなりますけど...。

いえ、SFINAEを使わない方向で実装し直します。

試したのはsize_c_sample関数の中なので普通にstatic_assertされるはずです。

いや、エラーメッセージと @Nagarei さんの検証結果的に、上に上げたコードがassertされないとおかしいなと思いまして。

https://github.com/Nagarei/DxLibEx/commit/72e0504a30e4aa877aca47bde071838ab0f38cb3 は型制約かけるのが第二引数ではなく第一引数になっていたというバグの修正なのでこの件の解決にはつながらないはずです

yumetodo commented 8 years ago

@Nagarei SFINAEを使わない形に戻しましたが、どうでしょうか?

Nagarei commented 8 years ago

db61fc7 で前者のは解決できました。

後者

    static_assert(std::is_same<unsigned, decltype(s13.width * 2U)>::value, "error3");

こんなのも試してみましたが、error3は表示されませんでした。ほんとに訳が分からない。

yumetodo commented 8 years ago

すみませんがこれの結果教えて下さい

#include <utility>//std::pair
template<typename T1, typename T2> auto f(const std::pair<T1, T1>& p, T2 n) -> decltype(p.first + n)
{
    static_assert(!std::is_same<unsigned int, decltype(p.first + n)>::value, "unsigned int");
    static_assert(!std::is_same<const unsigned int, decltype(p.first + n)>::value, "const unsigned int");
    static_assert(!std::is_same<int, decltype(p.first + n)>::value, "int");
    static_assert(!std::is_same<const int, decltype(p.first + n)>::value, "const int");
    return p.first + n;
}
int main()
{
    const int n = 9;
    const auto p = std::make_pair(3, 1);
    f(p, n);
    return 0;
}
Nagarei commented 8 years ago

コンパイル結果

1>c:\...\source.cpp(6): error C2338: int
1>          c:\...\source.cpp(14) : コンパイルされたクラスの テンプレート のインスタンス化 'T2 f<int,int>(const std::pair<int,int> &,T2)' の参照を確認してください
1>          with
1>          [
1>              T2=int
1>          ]
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========
yumetodo commented 8 years ago

VS2013環境を作ったので試したら、これはひどい。

    static_assert(!std::is_same<int, decltype(p.first + n)>::value, "int");

これをコメントアウトすればコンパイルエラーにはならないのか・・・、ますます謎。

yumetodo commented 8 years ago
#include <utility>//std::pair
#include <type_traits>
template<typename T1, typename T2, typename std::enable_if<std::is_arithmetic<T2>::value, std::nullptr_t>::type = nullptr>
auto f(const std::pair<T1, T1>& p, T2 n) -> decltype(p.first + n)
{
    static_assert(!std::is_same<unsigned int, decltype(p.first + n)>::value, "unsigned int");
    static_assert(!std::is_same<const unsigned int, decltype(p.first + n)>::value, "const unsigned int");
    //static_assert(!std::is_same<int, decltype(p.first + n)>::value, "int");
    static_assert(!std::is_same<const int, decltype(p.first + n)>::value, "const int");
    return p.first + n;
}
int main()
{
    int n = 9;
    auto p = std::make_pair(3, 1);
    f(p, n);
    return 0;
}

このコードだと、Visual Studio 2013 Update 5は問題なし、Visual Studio 22013 November CTPでは

1>------ ビルド開始: プロジェクト:tmp_test, 構成:Debug Win32 ------
1>  Source.cpp
1>c:\users\j.pierreno\documents\visual studio 2013\projects\tmp_test\tmp_test\source.cpp(4): error C2440: 'default argument' : cannot convert from 'nullptr' to 'std::enable_if<std::is_arithmetic<T2>::value,std::nullptr_t>::type'
1>          'std::enable_if<std::is_arithmetic<T2>::value,std::nullptr_t>::type' may be a value type at runtime: consider using 'std::enable_if<std::is_arithmetic<T2>::value,std::nullptr_t>::type()' instead
1>c:\users\j.pierreno\documents\visual studio 2013\projects\tmp_test\tmp_test\source.cpp(16): error C2783: 'unknown-type f(const std::pair<T1,T1> &,T2)' : could not deduce template argument for '__formal'
1>          c:\users\j.pierreno\documents\visual studio 2013\projects\tmp_test\tmp_test\source.cpp(4) : see declaration of 'f'
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========
yumetodo commented 8 years ago
    template <typename T1, typename T2, std::enable_if_t<std::is_arithmetic<T2>::value, std::nullptr_t> = nullptr>
    auto operator *(const size_c<T1>& l, T2 r) DXLE_NOEXCEPT_OR_NOTHROW
        ->size_c<decltype(l.width * r)>
    {
        return{ l.width * r, l.height * r };
    }

これがダメな原因の一つの可能性。

    template <typename T1, typename T2, std::enable_if_t<std::is_arithmetic<T2>::value, std::nullptr_t> = nullptr>
    auto operator *(const size_c<T1>& l, T2 r) DXLE_NOEXCEPT_OR_NOTHROW
        ->size_c<decltype(std::declval<std::remove_cv_t<T1>>() * std::declval<std::remove_cv_t<T2>>())>
    {
        return{ l.width * r, l.height * r };
    }

これならいけるか・・・?

yumetodo commented 8 years ago

これでうまく行った気がする。2013 November CTPはダメですね。

yumetodo commented 8 years ago

対応コンパイラから2013 November CTPが外れたのでfixしたと思います。