Nagarei / DxLibEx

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

座標系クラスのcopy/move ctorのconstexprについて #52

Open yumetodo opened 8 years ago

yumetodo commented 8 years ago

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

Nagarei commented 8 years ago

問題は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なオブジェクトのデフォルトコンストラクタはユーザーが定義する必要があるとのこと。

何が正しいのか分からなくなってきたので、とりあえず結論を保留して、調査結果だけ書いておきます。

yumetodo commented 8 years ago

うーん、なんだかよくわからない・・・。Clangの結果が。

yumetodo commented 8 years ago

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のバグ?

Nagarei commented 8 years ago

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.

と書いてありますね。

yumetodo commented 8 years ago

あー、そういやそんな話あったな、というかそのサイト見たことあるぞ・・・。

yumetodo commented 8 years ago

とりあえずdefault/delete指定はmove系およびconstexprが絡む場合は使わないとして、現状は問題ない・・・のかな