Closed Nagarei closed 8 years ago
なんだって!? ・・・それは2013 November CTPのことでいいですか?2013そのものにはnoexceptないですし
あと、私2013消しちゃったので検証できないんですが、2013Update4と2013 November CTPの_MSC_FULL_VER
ってなんでしたっけ。
焦ったけどTrailing return types(N2541)自体はVisual Studio 2010で実装されてるな。 https://msdn.microsoft.com/ja-jp/library/hh567368.aspx
僕のVS2013は_MSC_FULL_VERが180040629になってます。 これだとDXLE_NOEXCEPT_OR_NOT_THROWがnoexceptに展開さますが、どうもそれが原因でコンパイルエラーになっているようです。 たぶんvisualc.hppの
#if _MSC_FULL_VER < 180031101
# define DXLE_NO_CXX11_NOEXCEPT
#endif
ここが間違っているのではないかと思います。 ただ自分に正確な知識がないので直せないという状況です。
_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 |
どうもNobemver CTPの判定をミスっていたようです。しっかし、Nobemver CTPだけなんで番号が変則的なんだ。
これでどうでしょうか?
auto f() throw() -> int;
という書き方が認められるなら通ると思うんですが。
とりあえず報告です。新しいエラーが二つ出てしまいました。
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> この変換を実行可能なユーザー定義変換演算子がないか、または演算子を呼び出せません。
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 };
にした結果を知りたいですね・・・
後者
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>
になっています。
前者
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; }
}
これでとりあえずエラーは出なくなりました。何なんだいったい。
前者:もはや謎
後者
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されましたっけ。されないはずなんですが・・・。
前者 上ので書き直して良いですか?汚くはなりますけど...。 後者 試したのはsize_c_sample関数の中なので普通にstatic_assertされるはずです。 72e0504 にした後も継続してエラーになっています。
上ので書き直して良いですか?汚くはなりますけど...。
いえ、SFINAEを使わない方向で実装し直します。
試したのはsize_c_sample関数の中なので普通にstatic_assertされるはずです。
いや、エラーメッセージと @Nagarei さんの検証結果的に、上に上げたコードがassertされないとおかしいなと思いまして。
https://github.com/Nagarei/DxLibEx/commit/72e0504a30e4aa877aca47bde071838ab0f38cb3 は型制約かけるのが第二引数ではなく第一引数になっていたというバグの修正なのでこの件の解決にはつながらないはずです
@Nagarei SFINAEを使わない形に戻しましたが、どうでしょうか?
db61fc7 で前者のは解決できました。
後者
static_assert(std::is_same<unsigned, decltype(s13.width * 2U)>::value, "error3");
こんなのも試してみましたが、error3は表示されませんでした。ほんとに訳が分からない。
すみませんがこれの結果教えて下さい
#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;
}
コンパイル結果
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 スキップ ==========
VS2013環境を作ったので試したら、これはひどい。
static_assert(!std::is_same<int, decltype(p.first + n)>::value, "int");
これをコメントアウトすればコンパイルエラーにはならないのか・・・、ますます謎。
#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 スキップ ==========
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 };
}
これならいけるか・・・?
これでうまく行った気がする。2013 November CTPはダメですね。
対応コンパイラから2013 November CTPが外れたのでfixしたと思います。
noexceptですが、どうもVS2013ではうまく認識してくれていないみたいです。