nguage/expressions#Expression-equivalence "cpp/language/expressions") to  [ ranges::  data  ](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/data) (  static_cast  < CT  && > (  t  )  )  .  The return type is equivalent to  [ std::  remove_reference_t  ](http://en.cppreference.com/w/cpp/types/remove_reference) < [ ranges::  range_reference_t  ](http://en.cppreference.com/w/cpp/ranges/iterator_t) < CT  >> *  .  |  (until C++23)   
---|---  
If the argument is an lvalue or  [ ranges::  enable_borrowed_range
](http://en.cppreference.com/w/cpp/ranges/borrowed_range) < [ std::
remove_cv_t  ](http://en.cppreference.com/w/cpp/types/remove_cv) < T  >> is
true  , then a call to ` ranges::cdata ` is [ expression-equivalent
](/w/cpp/language/expressions#Expression-equivalence
"cpp/language/expressions") to:

  * /*as-const-pointer*/  (  [ ranges::  data  ](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/data) (  /*possibly-const-range*/  (  t  )  )  )  . 

The return type is equivalent to  [ std::  remove_reference_t  ](http://en.cppreference.com/w/cpp/types/remove_reference) < [ ranges::  range_const_reference_t  ](http://en.cppreference.com/w/cpp/ranges/iterator_t) < T  >> *  .  In all other cases, a call to ` ranges::cdata ` is ill-formed, which can result in [ substitution failure ](/w/cpp/language/sfinae "cpp/language/sfinae") when the call appears in the immediate context of a template instantiation.  |  (since C++23)   
---|---  
  
If  [ ranges::  cdata  ](http://en.cppreference.com/w/cpp/ranges-ranges-
placeholder/cdata) (  t  )  is valid, then it returns a pointer to an object
of constant type  (since C++23)  .

###  Customization point objects

The name ` ranges::cdata ` denotes a _customization point object_ , which is a
const [ function object ](/w/cpp/named_req/FunctionObject "cpp/named
req/FunctionObject") of a [ literal ](/w/cpp/named_req/LiteralType "cpp/named
req/LiteralType") [ ` semiregular ` ](/w/cpp/concepts/semiregular
"cpp/concepts/semiregular") class type. For exposition purposes, the cv-
unqualified version of its type is denoted as ` ___cdata_fn_ ` .

All instances of ` ___cdata_fn_ ` are equal. The effects of invoking different
instances of type ` ___cdata_fn_ ` on the same arguments are equivalent,
regardless of whether the expression denoting the instance is an lvalue or
rvalue, and is const-qualified or not (however, a volatile-qualified instance
is not required to be invocable). Thus, ` ranges::cdata ` can be copied freely
and its copies can be used interchangeably.

Given a set of types ` Args... ` , if  [ std::  declval
](http://en.cppreference.com/w/cpp/utility/declval) < Args  > (  )  ...  meet
the requirements for arguments to ` ranges::cdata ` above, ` ___cdata_fn_ `
models  

  * [ std::  invocable  ](http://en.cppreference.com/w/cpp/concepts/invocable) < __cdata_fn, Args...  > , 
  * [ std::  invocable  ](http://en.cppreference.com/w/cpp/concepts/invocable) < const  __cdata_fn, Args...  > , 
  * [ std::  invocable  ](http://en.cppreference.com/w/cpp/concepts/invocable) < __cdata_fn  & , Args...  > , and 
  * [ std::  invocable  ](http://en.cppreference.com/w/cpp/concepts/invocable) < const  __cdata_fn  & , Args...  > .   

Otherwise, no function call operator of ` ___cdata_fn_ ` participates in
overload resolution.

###  [ [ edit ](/mwiki/index.php?title=cpp/ranges/cdata&action=edit&section=1
"Edit section: Example") ]  Example

Run this code

    
    
    #include <cstring>
    #include <iostream>
    #include <ranges>
    #include <string>
     
    int main()
    {
        [std::string](http://en.cppreference.com/w/cpp/string/basic_string) src {"hello world!\n"};
     
    //  std::ranges::cdata(src)[0] = 'H'; // error, src.data() is treated as read-only
        std::[ranges::data](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/data)(src)[0] = 'H'; // OK, src.data() is a non-const storage
     
        char dst[20]; // storage for a C-style string
        [std: