3

I am trying to initialize a span<const T*> — that is, a list of pointers to const data. However, the rules for const conversion amongst pointers and span<>'s available constructors are thwarting me.

I'm sure there's a way to do it, but I cannot find the right casting/invocation.

Aside: I'm actually not using C++20, but tcb::span, which uses the older P0122R7 set of constructors, with (pointer,size) rather than iterators. But I suspect getting something working on C++20 will get me in the right direction.

The below example demonstrates what I'm trying to do, and some failed attempts at fixing it:

Live link on Godbolt

#include<span>
#include<vector>
#include<iostream>
using std::cout;
using std::endl;

int main() {

    int a = 0;
    int b = 1;
    int c = 2;

    std::vector<int*> pointers = { &a, &b, &c };
    
    // This declaration does not work; no span<> constructor matches it.
    std::span<const int*> cspan(&pointers[0], pointers.size());

    // This declaration also does not work; the cast is fine, but still no span<> constructor matches.
    //std::span<const int*> cspan(static_cast<const int *const*>(&pointers[0]), pointers.size());

    // This declaration works, but then "cspan" cannot be sorted, since
    // the pointers themselves are const, and cannot be overwritten.
    //std::span<const int* const> cspan(&pointers[0], pointers.size());
    
    // Sort the span (by address)
    // This is the code I want to work. I just need some way to declare 'cspan' properly.
    std::sort(cspan.begin(), cspan.end());
    
    return 0;
}

Any ideas?

jwd
  • 10,837
  • 3
  • 43
  • 67

1 Answers1

1

What's wrong with:

#include<span>
#include<vector>
#include<iostream>
using std::cout;
using std::endl;

int main() {

    int a = 0;
    int b = 1;
    int c = 2;

    std::vector<int*> pointers = { &a, &b, &c };

    std::span<const int*> cspan(const_cast<const int**>(pointers.data()), pointers.size());

    std::sort(cspan.begin(), cspan.end());
    
    return 0;
}
ALX23z
  • 4,456
  • 1
  • 11
  • 18
  • Well, I suppose it does. But I wonder if there is something unsafe about it? [This description](http://c-faq.com/ansi/constmismatch.html) of the underlying issue shows some potential bad usage, but maybe span<> prevents such a thing? I'm just worried that I'm casting away something important (: – jwd Jan 20 '22 at 00:43
  • @jwd nope, `span` doesn't help at all with this. Since you want to sort and modify the pointers. But at the same time you want the pointers to be towards `const` which allows original `int*` to be filled with `const int*` which is a safety problem. That's why the `const_cast` is used as it allows you to cast ignoring these concerns with const correctness. – ALX23z Jan 20 '22 at 01:03