我必须为工作构建一个小的OpenGL包装器。我正在努力避免为我的所有课程编写复制构造函数和复制作业。
一种非常懒惰且永远不会写副本的方法是使用指针,但由于指针是邪恶的,我试图专门使用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;
(...)
我尝试了两种不同的构造函数:
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))
{
}
我想做的是能够传递lvalue或rvalue共享指针传递,但它不起作用,每次都会崩溃,除非我在前进时使用左值。
// 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上的rvalue不起作用。 std :: move上的左值或右值不起作用。它只是在调用std :: shared_ptr构造函数时挂起程序(在程序构造函数内)。
我看了斯科特梅尔斯的全民参考谈话,我以为我理解这一点,这发生在我身上。
答案 0 :(得分: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不会被移除。
这导致我怀疑其他地方的另一个问题。如果您可以隔离出现问题的SSCCE,请告诉我。