c++ 将连续容器类型的连续容器类型自动转换为另一通用“连续容器类型视图”

ijxebb2r  于 2023-05-08  发布在  其他
关注(0)|答案(1)|浏览(460)

我有以下代码godbolt链接:

#include <iostream>
#include <array>
#include <vector>
#include <span>
#include <cstdint> 
#include <string>

template <typename T>
constexpr auto type_name() {
    std::string_view name, prefix, suffix;
#ifdef __clang__
    name = __PRETTY_FUNCTION__;
  prefix = "auto type_name() [T = ";
  suffix = "]";
#elif defined(__GNUC__)
    name = __PRETTY_FUNCTION__;
  prefix = "constexpr auto type_name() [with T = ";
  suffix = "]";
#elif defined(_MSC_VER)
    name = __FUNCSIG__;
    prefix = "auto __cdecl type_name<";
    suffix = ">(void)";
#endif
    name.remove_prefix(prefix.size());
    name.remove_suffix(suffix.size());
    return name;
}
template <typename T>
concept ContiguousContainer = requires (T t) {
    t.data();
    t.size();
};

template<typename T> 
struct proxy{
            template<typename V> 
        proxy( const V & v ) noexcept
                : m_size(  v.size() )
        , m_ptr( v.data() )
        {}

    std::size_t m_size; 
    const T* m_ptr; 
};
template<typename V>
proxy(const V &v) noexcept -> proxy<typename V::value_type>;

template<ContiguousContainer T> 
int foo(const proxy<T>& temp){
return 1; 
}

int main(){
    std::vector<std::vector<int>> vec;

    auto temp_0 = foo<decltype(vec)::value_type>(vec);
    auto temp_1 = proxy(vec); //works as intended
    std::cout << type_name<decltype(temp_1)>() << std::endl; 
    auto temp_2 = foo(vec); //doesn't compile. 

    return 0;
}

我想做的是把最后一句台词

auto temp_2 = foo(vec);

我试图让std::vector<std::vector<int>>类型的vec强制转换为proxy<std::vector<int>>。最终我希望foo接受任何容器的容器,但特别是将它们粗略地放入我的类型proxy中,在我的实际代码中,它有其他好处(可以接受单个值,也可以接受初始化列表,因此我希望它进入该类型)。现在,我可以在没有模板的情况下,简单地使用构造函数来转换(temp_1),但我不能用函数来这样做。我希望有一个函数,可以接受任何容器(以.data().size()为成员)作为参数,并自动将其转换为proxy类型。但我得到了以下错误:

x86-64 gcc 13.1
x86-64 gcc 13.1
-std=c++20
123
<Compilation failed>

# For more information see the output window
x86-64 gcc 13.1 - 1753ms
<source>: In function 'int main()':
<source>:61:22: error: no matching function for call to 'foo(std::vector<std::vector<int> >&)'
   61 |     auto temp_2 = foo(vec); //doesn't compile.
      |                   ~~~^~~~~
<source>:51:5: note: candidate: 'template<class T>  requires  ContiguousContainer<T> int foo(const proxy<T>&)'
   51 | int foo(const proxy<T>& temp){
      |     ^~~
<source>:51:5: note:   template argument deduction/substitution failed:
<source>:61:22: note:   'std::vector<std::vector<int> >' is not derived from 'const proxy<T>'
   61 |     auto temp_2 = foo(vec); //doesn't compile.
      |                   ~~~^~~~~
ASM generation compiler returned: 1
<source>: In function 'int main()':
<source>:61:22: error: no matching function for call to 'foo(std::vector<std::vector<int> >&)'
   61 |     auto temp_2 = foo(vec); //doesn't compile.
      |                   ~~~^~~~~
<source>:51:5: note: candidate: 'template<class T>  requires  ContiguousContainer<T> int foo(const proxy<T>&)'
   51 | int foo(const proxy<T>& temp){
      |     ^~~
<source>:51:5: note:   template argument deduction/substitution failed:
<source>:61:22: note:   'std::vector<std::vector<int> >' is not derived from 'const proxy<T>'
   61 |     auto temp_2 = foo(vec); //doesn't compile.
      |                   ~~~^~~~~
Execution build compiler returned: 1

有没有办法达到这个效果?

gab6jxml

gab6jxml1#

我认为你所需要的就是这个(可能是代替你当前的foo实现,它似乎没有任何用处):

template<typename T> requires ContiguousContainer <T>
auto foo(const T& temp){
    return proxy (temp);
}

Live demo
参考OP下面的评论,可以通过修改ContiguousContainer概念(现在没有很好的命名)来获得所需的行为,如下所示:

template <typename T>
concept ContiguousContainer = requires (T t) {
    t.data();
    t.size();
    t.data ()->data ();
    t.data ()->size ();
};

Live demo
或者甚至:

template <typename T>
concept ContiguousContainer = requires (T t) {
    t.data ()->data ();
    t.data ()->size ();
};

合和

相关问题