小编cj.*_*cj.的帖子

如何解决C++命名空间和全局函数之间的名称冲突?

如果我在log某处定义名称空间并使其在全局范围内可访问,则会与double log(double)标准cmath标题冲突.实际上,大多数编译器似乎也同意它 - 大多数版本的SunCC,MSVC,GCC - 但GCC 4.1.2没有.

不幸的是,似乎没有办法解决歧义,因为using声明对于命名空间标识符是不合法的.你知道我可以log::Log在全局命名空间中编写任何方式cmath吗?

谢谢.

编辑:有人会知道C++ 03标准对此有何看法?我原以为范围运算符足以消除log下面代码示例中的使用歧义.

#include <cmath>

namespace foo
{

namespace log
{

struct Log { };

} // namespace log

} // namespace foo


using namespace foo;

int main()
{
    log::Log x;

    return 0;
}

// g++ (GCC) 4.1.2 20070115 (SUSE Linux)

// log.cpp: In function `int main()':
// log.cpp:20: error: reference to `log' is ambiguous
// /usr/include/bits/mathcalls.h:110: …
Run Code Online (Sandbox Code Playgroud)

c++ namespaces name-conflict

10
推荐指数
2
解决办法
1万
查看次数

如何处理无法释放智能指针中包含的资源?

当表示资源的对象包含在共享指针中时,如何处理资源释放期间的错误?

编辑1:

用更具体的术语来说明这个问题:许多C风格的接口都有一个分配资源的功能,一个用来释放它.POSIX系统上的文件描述符是open(2)和close(2),XOpenDisplay和XCloseDisplay是连接到X服务器的例子,sqlite3_open和sqlite3_close是连接到SQLite数据库的例子.

我喜欢将这些接口封装在C++类中,使用Pimpl习惯用法隐藏实现细节,并提供一个返回共享指针的工厂方法,以确保在没有对它的引用时释放资源.

但是,在上面给出的所有示例和许多其他示例中,用于释放资源的函数可能会报告错误.如果析构函数调用此函数,我不能抛出异常,因为通常析构函数不能抛出.

另一方面,如果我提供一个公共方法来释放资源,我现在有一个具有两种可能状态的类:一个资源有效,另一个资源已经释放.这不仅会使类的实现变得复杂,而且还会导致错误使用.这很糟糕,因为界面的目标应该是无法使用错误.

如果对这个问题有任何帮助,我将不胜感激.

问题的原始陈述以及对可能解决方案的想法如下.

编辑2:

现在有一个关于这个问题的赏金.解决方案必须满足以下要求:

  1. 当且仅当没有对它的引用时才释放资源.
  2. 可以明确地销毁对资源的引用.如果在释放资源时发生错误,则抛出异常.
  3. 无法使用已发布的资源.
  4. 引用计数和释放资源是线程安全的.

解决方案满足以下要求:

  1. 它使用boost提供的共享指针,C++技术报告1(TR1)和即将推出的C++标准C++ 0x.
  2. 它是通用的.资源类只需要实现资源的释放方式.

感谢您的时间和想法.

编辑3:

感谢所有回答我问题的人.

阿尔斯克的回答满足了赏金中所要求的一切,并被接受了.在多线程代码中,此解决方案需要单独的清理线程.

我添加了另一个答案,其中清理期间的任何异常都被实际使用资源的线程抛出,而不需要单独的清理线程.如果你仍然对这个问题感兴趣(这让我很烦恼),请发表评论.

智能指针是安全管理资源的有用工具.此类资源的示例是内存,磁盘文件,数据库连接或网络连接.

// open a connection to the local HTTP port
boost::shared_ptr<Socket> socket = Socket::connect("localhost:80");
Run Code Online (Sandbox Code Playgroud)

在典型的场景中,封装资源的类应该是不可复制的和多态的.支持这一点的一个好方法是提供一个返回共享指针的工厂方法,并声明所有构造函数都是非公共的.现在可以自由地复制和分配共享指针.当没有对它的引用仍然存在时,该对象将被自动销毁,然后析构函数将释放该资源.

/** A TCP/IP connection. */
class Socket
{
public:
    static boost::shared_ptr<Socket> connect(const std::string& address);
    virtual ~Socket();
protected:
    Socket(const std::string& address);
private:
    // not implemented
    Socket(const Socket&);
    Socket& …
Run Code Online (Sandbox Code Playgroud)

c++ smart-pointers raii

9
推荐指数
1
解决办法
2195
查看次数

如何实现可以用void实例化的智能指针?

一些智能指针模板,例如boost :: shared_ptr,可以用void实例化以保存任意对象:

http://www.boost.org/doc/libs/1_39_0/libs/smart_ptr/sp_techniques.html#pvoid

下面是一个最小的scoped_ptr实现.当用void实例化时,编译器会抱怨在解除引用运算符中形成了非法的"void to".似乎"替代失败不是错误"(SFINAE)规则并未涵盖这种情况.

那么如何实现scoped_ptr呢?特别是,是否有替代编写模板专业化?这将导致使用真实的智能指针实现进行大量代码重复.

#include <cstdlib>

template<typename T>
void destroy(T* ptr)
{
    delete ptr;
}

class scoped_ptr_impl_base
{
public:
    virtual ~scoped_ptr_impl_base() { }
};

template<typename T, typename F>
class scoped_ptr_impl : public scoped_ptr_impl_base
{
public:
    scoped_ptr_impl(T* ptr, F dtor)
        : m_ptr(ptr), m_dtor(dtor)
    {
    }

    virtual ~scoped_ptr_impl()
    {
        m_dtor(m_ptr);
    }

private:
    T* m_ptr;
    F m_dtor;
};

template<typename T>
class scoped_ptr
{
public:
    explicit scoped_ptr(T* ptr = 0)
        : m_ptr(ptr),
          m_impl(new scoped_ptr_impl<T, void (*)(T*)>(&destroy<T>))
    {
    }

    template<typename F>
    scoped_ptr(T* …
Run Code Online (Sandbox Code Playgroud)

c++ templates smart-pointers

4
推荐指数
1
解决办法
1801
查看次数