3

作業用に小さなOpenGLラッパーを作成する必要があります。すべてのクラスにコピーコンストラクターとコピー割り当てを記述しないようにしています。

本当に怠惰でコピーを書かないようにする1つの方法は、ポインターを使用することですが、ポインターは悪であるため、私は排他的に使用しようとしていますstd::shared_ptr

問題は、std::shared_ptr値で受け取るコンストラクターを使用するとプログラムがクラッシュし、完全転送を使用すると、左辺値を渡した場合にのみ機能することです。

// this class doesn't have any default, copy constructors.
class Dep
{
    Dep(std::string path, GLenum type);
};

class Program
{
std::shared_ptr<Dep> dep1;
std::shared_ptr<Dep> dep2;

(...)

私は2種類のコンストラクターを試しました:

template <class T, class = typename std::enable_if<std::is_constructible<std::shared_ptr<Dep>, T>::value>::type>
Program(T&& dep1, T&& dep2)
: dep1(std::forward<T>(dep1)), dep2(std::forward<T>(dep2))
{
}

ともう1つ

Program(std::shared_ptr<Dep> dep1, std::shared_ptr<Dep> dep2)
: dep1(std::move(dep1)), dep2(std::move(dep2))
{
}

私がやりたいのは、左辺値または右辺値の共有ポインターのいずれかを渡すことができることですが、前方のポインターで左辺値を使用しない限り、毎回クラッシュするわけではありません。

// passing these work on the std::forward one, but that's the only case it works
// if i try to use std::make_shared as parameter (for rvalue) it crashes on both
// the std::move and std::forward ones.
auto vs = std::make_shared<GLShader>("TriangleVS.glsl", GL_VERTEX_SHADER);
auto fs = std::make_shared<GLShader>("TriangleFS.glsl", GL_FRAGMENT_SHADER);

要約:std::forwardの左辺値は機能します。std::forwardの右辺値は機能しません。std::moveの左辺値または右辺値は機能しません。std :: shared_ptrコンストラクターが呼び出されたときに(プログラムコンストラクター内で)プログラムをハングさせるだけです。

私はスコットメイヤーズの普遍的な参照が話すのを見て、私はこれを理解していると思いました、そしてこれは私に起こります。

4

1 に答える 1

1

このコードには何の問題もありません。http ://ideone.com/jlShgBでも問題なくテストされています。

#include <memory>
#include <utility>
#include <string>
#include <cassert>

enum GLenum { foo };

// this class doesn't have any default, copy constructors.
struct Dep
{
    Dep(std::string path, GLenum type) {}
    Dep() = delete;
    Dep(Dep const&) = delete;
};

struct Program
{
    std::shared_ptr<Dep> dep1;
    std::shared_ptr<Dep> dep2;

#if 1
    template <class T, class = typename std::enable_if<std::is_constructible<std::shared_ptr<Dep>, T>::value>::type>
    Program(T&& dep1, T&& dep2)
        : dep1(std::forward<T>(dep1)), dep2(std::forward<T>(dep2))
    {
    }
#else
    Program(std::shared_ptr<Dep> dep1, std::shared_ptr<Dep> dep2)
        : dep1(std::move(dep1)), dep2(std::move(dep2))
    {
    }
#endif
};

int main()
{
    auto dep1 = std::make_shared<Dep>("dep1", foo);
    auto dep2 = std::make_shared<Dep>("dep2", foo);
    Program p(std::move(dep1), std::move(dep2));

    assert(!dep1 && !dep2);
}

もちろん、に変更#if 1する#if 0と、dep1 / dep2はから移動されないため、assertは例外を発生させます。

これは私をどこか別の問題に疑わせることにつながります。問題のあるSSCCEを特定できる場合は、お知らせください。

于 2012-11-14T21:21:18.710 に答える