“初始化”:无法从“zallocator<char>”转换为“zallocator<U>”

use*_*334 1 c++

我试图尝试此页面上给出的 C++ 中的 openssl 示例。该项目示例文件名为 env-encrypt.cxx,可以在该页面上的 tar.gz 内下载。

当我尝试在 Visual Studio 2017 上运行该示例时。我收到以下错误:'Initializing': cannot convert from 'zallocator<char>' to 'zallocator<U>' in file xstring line 1998

这是我得到的输出:

1>------ Build started: Project: ConsoleApplication3, Configuration: Debug Win32 ------
1>ConsoleApplication3.cpp
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.15.26726\include\xstring(1998): error C2440: 'initializing': cannot convert from 'zallocator<char>' to 'zallocator<U>'
1>        with
1>        [
1>            U=std::_Container_proxy
1>        ]
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.15.26726\include\xstring(1998): note: No constructor could take the source type, or constructor overload resolution was ambiguous
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.15.26726\include\xstring(1997): note: while compiling class template member function 'void std::_String_alloc<std::_String_base_types<_Elem,_Alloc>>::_Free_proxy(void)'
1>        with
1>        [
1>            _Elem=char,
1>            _Alloc=zallocator<char>
1>        ]
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.15.26726\include\xstring(1949): note: see reference to function template instantiation 'void std::_String_alloc<std::_String_base_types<_Elem,_Alloc>>::_Free_proxy(void)' being compiled
1>        with
1>        [
1>            _Elem=char,
1>            _Alloc=zallocator<char>
1>        ]
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.15.26726\include\xstring(2066): note: see reference to class template instantiation 'std::_String_alloc<std::_String_base_types<_Elem,_Alloc>>' being compiled
1>        with
1>        [
1>            _Elem=char,
1>            _Alloc=zallocator<char>
1>        ]
1>c:\users\xxx\source\repos\consoleapplication3\consoleapplication3\consoleapplication3.cpp(86): note: see reference to class template instantiation 'std::basic_string<char,std::char_traits<char>,zallocator<char>>' being compiled
1>Done building project "ConsoleApplication3.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Run Code Online (Sandbox Code Playgroud)

为了让事情变得更容易,这是我下载的 env-encrypt.cxx 文件中的 zallocator 类:

template <typename T> 
struct zallocator
{
public:
    typedef T value_type;
    typedef value_type* pointer;
    typedef const value_type* const_pointer;
    typedef value_type& reference;
    typedef const value_type& const_reference;
    typedef std::size_t size_type;
    typedef std::ptrdiff_t difference_type;

    pointer address(reference v) const { return &v; }
    const_pointer address(const_reference v) const { return &v; }

    pointer allocate(size_type n, const void* hint = 0) {
        if (n > std::numeric_limits<size_type>::max() / sizeof(T))
            throw std::bad_alloc();
        return static_cast<pointer> (::operator new (n * sizeof(value_type)));
    }

    void deallocate(pointer p, size_type n) {
        OPENSSL_cleanse(p, n * sizeof(T));
        ::operator delete(p);
    }

    size_type max_size() const {
        return std::numeric_limits<size_type>::max() / sizeof(T);
    }

    template<typename U>
    struct rebind
    {
        typedef zallocator<U> other;
    };

    void construct(pointer ptr, const T& val) {
        new (static_cast<T*>(ptr)) T(val);
    }

    void destroy(pointer ptr) {
        static_cast<T*>(ptr)->~T();
    }

#if __cpluplus >= 201103L
    template<typename U, typename... Args>
    void construct(U* ptr, Args&&  ... args) {
        ::new (static_cast<void*> (ptr)) U(std::forward<Args>(args)...);
    }

    template<typename U>
    void destroy(U* ptr) {
        ptr->~U();
    }
#endif
};
Run Code Online (Sandbox Code Playgroud)

这是 secure_string 的 typedef,它正在调用 zallocator,这似乎是问题所在:

typedef std::basic_string<char, std::char_traits<char>, zallocator<char> > secure_string;
Run Code Online (Sandbox Code Playgroud)

如果您想查看完整的源代码,可以从我链接的页面下载。

编辑:当我添加这一行时:

template<class U> zallocator(const zallocator<U>&) noexcept { }
Run Code Online (Sandbox Code Playgroud)

对于此reddit帖子中建议的类定义,我得到另一个异常: 'zallocator::zallocator': 没有合适的默认构造函数可用。

我尝试添加没有参数的构造函数,如下所示:`

template<class U> zallocator() noexcept { }
Run Code Online (Sandbox Code Playgroud)

`,但仍然遇到相同的错误

Mic*_*ler 5

查看分配器文档以及cppreference 上的分配器完整性要求。最后一个链接包含以下最小 c++17 分配器示例:

template <class T>
struct Mallocator {
  typedef T value_type;
  Mallocator() = default;
  template <class U> constexpr Mallocator(const Mallocator<U>&) noexcept {}
  [[nodiscard]] T* allocate(std::size_t n) {
    if(n > std::size_t(-1) / sizeof(T)) throw std::bad_alloc();
    if(auto p = static_cast<T*>(std::malloc(n*sizeof(T)))) return p;
    throw std::bad_alloc();
  }
  void deallocate(T* p, std::size_t) noexcept { std::free(p); }
};
template <class T, class U>
bool operator==(const Mallocator<T>&, const Mallocator<U>&) { return true; }
template <class T, class U>
bool operator!=(const Mallocator<T>&, const Mallocator<U>&) { return false; }
Run Code Online (Sandbox Code Playgroud)

这应该会让您了解如何修复代码。


您缺少比较运算符:operator==operator!=

template <typename U>
friend bool operator==(const zallocator<T> & a, const zallocator<U> & b)
{
    return true;
}
template <typename U>
friend bool operator!=(const zallocator<T> & a, const zallocator<U> & b)
{
    return false;
}
Run Code Online (Sandbox Code Playgroud)

还有几个构造函数:

constexpr zallocator() noexcept = default;
template< class U>
constexpr zallocator(const zallocator<U>& other) noexcept
{
}
Run Code Online (Sandbox Code Playgroud)


在尝试修复构造函数的错误时,您写道:

template<class U> zallocator() noexcept { }
Run Code Online (Sandbox Code Playgroud)

但这不是默认构造函数。默认构造函数不应该被模板化。