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

问题描述 投票:0回答:1

我有以下代码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);

上班。我正在尝试让

vec
类型的
std::vector<std::vector<int>>
强制转换为函数中的
proxy<std::vector<int>>
。最终,我希望 foo 接受任何 container of containers,但特别将它们粗略化为我的类型,
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

我有办法达到这个效果吗?

c++ templates c++20 implicit-conversion template-argument-deduction
1个回答
0
投票

我认为您所需要的就是这个(可能代替您当前实施的

foo
,这似乎毫无用处):

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

现场演示


参考OP在下面的评论,可以通过修改

ContiguousContainer
概念(现在没有很好地命名)来获得所需的行为,如下所示:

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

现场演示

甚至:

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

呵呵

© www.soinside.com 2019 - 2024. All rights reserved.