Перемещение std :: shared_ptr приводит к сбою программы

Я должен создать небольшую оболочку OpenGL для работы. Я пытаюсь избежать написания конструкторов копирования и назначения копирования для всех моих классов.

Единственный способ быть действительно ленивым и никогда не писать копии — это использовать указатели, но так как указатели являются злом, я пытаюсь использовать исключительно std::shared_ptr,

Проблема заключается в использовании конструктора, который получает std::shared_ptr по значению моя программа падает, а при использовании совершенной пересылки она работает только тогда, когда я передаю lvalue.

// 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))
{
}

а другой

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

То, что я хочу сделать, — это возможность передать pass или общий указатель lvalue или rvalue, но он не работает, он вылетает каждый раз, если я не использую lvalue на переднем.

// 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);

резюме: lvalue на std :: forward работает. rvalue на std :: forward не работает. lvalue или rvalue на std :: move one не работают. он просто вешает программу, когда вызывается конструктор std :: shared_ptr (внутри конструктора программы).

Я наблюдал за выступлениями Скотта Майерса, и мне показалось, что я это понимаю, и это происходит со мной.

3

Решение

Я не вижу ничего плохого в этом коде, и он проверяет нормально 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, assert вызовет исключение, потому что dep1 / dep2 не будет перемещен из.

Это заставляет меня подозревать другую проблему где-то еще. Если вы можете изолировать SSCCE, который показывает проблему, пожалуйста, дайте мне знать.

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector