DxLibEx
DxLibEx copied to clipboard
座標系クラスのcopy/move ctorのconstexprについて
https://gcc.gnu.org/ml/libstdc++/2012-10/msg00120.html
diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono
index 209f395..d920a7d 100644
--- a/libstdc++-v3/include/std/chrono
+++ b/libstdc++-v3/include/std/chrono
@@ -250,7 +250,10 @@ _GLIBCXX_END_NAMESPACE_VERSION
// 20.11.5.1 construction / copy / destroy
constexpr duration() = default;
- constexpr duration(const duration&) = default;
+ // NB: Make constexpr implicit. This cannot be explicitly
+ // constexpr, as any UDT that is not a literal type with a
+ // constexpr copy constructor will be ill-formed.
+ duration(const duration&) = default;
template<typename _Rep2, typename = typename
enable_if<is_convertible<_Rep2, rep>::value
https://twitter.com/bolero_MURAKAMI/status/709308206640537600
@yumetodo 直訳:暗黙にconstexpr指定される。非リテラル型な任意のUDT(User-Defined Type)に対して、constexprコピーコンストラクタはill-formedになるため、明示的にconstexpr指定すべきでない。
https://twitter.com/bolero_MURAKAMI/status/709308973850058752
@yumetodo つまり、duration<Rep> の Rep は非リテラル型なユーザ定義型である可能性があるため、明示的にconstexpr指定しないようにする変更。Rep がリテラル型である場合、トリビアルコピーコンストラクタは暗黙にconstexpr指定される。
というのを見て座標系クラスがどうなっているか見たんですが
//copy constructor
DXLE_CONSTEXPR_CLASS size_c(const size_c<value_type>& o) DXLE_NOEXCEPT_IF((std::is_nothrow_copy_constructible<value_type>::value)) : width(o.width), height(o.height) {}
//move constructor
DXLE_CONSTEXPR_CLASS size_c(size_c<value_type>&& o) DXLE_NOEXCEPT_OR_NOTHROW : width(std::move(o.width)), height(std::move(o.height)) {}
これ大丈夫なのかな、ダメな気がしてきたのでissue立てました
@Nagarei
問題はVC++2015で暗黙にconstexpr指定されない事と、VC++2013でmoveコンストラクタにdefaultが使えない事ですね...。
VC++2015では下のコードがエラーになります。
template<typename T>
class constexpr_class
{
public:
constexpr_class() = default;
T v = 10;
};
constexpr constexpr_class<int> c;
int main()
{
int arr[c.v];
return 0;
}
ちなみにconstexprを付けた状態で、UDTをTにいれてもVC++2015では問題ないです。
template<typename T>
class constexpr_class
{
public:
constexpr constexpr_class() = default;
T v = 10;
};
class non_constexpr_class
{
public:
non_constexpr_class(int) {}
};
constexpr constexpr_class<int> c;
int main()
{
int arr[c.v];
constexpr_class<non_constexpr_class> c2;
return 0;
}
あと、clangで試したら
default initialization of an object of const type 'const constexpr_class<int>' without a user-provided default constructor
と怒られました。constなオブジェクトのデフォルトコンストラクタはユーザーが定義する必要があるとのこと。
何が正しいのか分からなくなってきたので、とりあえず結論を保留して、調査結果だけ書いておきます。
うーん、なんだかよくわからない・・・。Clangの結果が。
Clang 3.7 http://melpon.org/wandbox/permlink/paW4sELvA5Q3j6lf Clang 3.8 http://melpon.org/wandbox/permlink/WxYsS6jvtknFfJzz Clang 3.9 http://melpon.org/wandbox/permlink/vyPJ0e6Za5I9LIyV GCC 5.2.0 http://melpon.org/wandbox/permlink/sI6mYNsHOxcjb71E GCC6.0.0 http://melpon.org/wandbox/permlink/1wnCFG0ioX9eiiOB
ほう・・・
もしかして:Clangのバグ?
clangのバグではないと思います。 http://d.hatena.ne.jp/tkng/20110419/1303176182 n3797には
If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class
type with a user-provided default constructor.
と書いてありますね。
あー、そういやそんな話あったな、というかそのサイト見たことあるぞ・・・。
とりあえずdefault/delete指定はmove系およびconstexprが絡む場合は使わないとして、現状は問題ない・・・のかな