Passing a pointer to an inline type defined on the fly in C ++

I want to call a library function (which I cannot change)

void function(int* i, char* c);

Is there a way to call a function that determines intand charon the fly?

i.e. sort of

function(&1, &'v');

instead

int int_1 = 1;
char char_1 = 'v';
function(&int_1, &char_v);

This will significantly reduce the length of my code, increasing readability.

+4
source share
6 answers

As others noted, the answer is no ...

You can simulate it by overloading function:

void function(int i, char c)
{
  function(&i, &c);
}

So now you can write function(1, 'v')

+7
source

Why do you need this? Passing a variable as a pointer does not const, indicates that the caller intends to change the passed parameter, so it cannot be rvalue.

, ( , ). , , , . , ,

+3

- .

function((int*)&(const int &)1, (char*)&(const char &)'v');

, . , , , .

- .

. , 'function' . , .

. ​​ "++". - , . , UB.

+2

FISOCPP , , .

:

function(&(int){1}, &(char){'v'});

, gcc , .

, , C ++, , C99.

0

++ 11:

#include <type_traits>
#include <iostream>

template <typename Param, typename Arg>
Param take_address_if_necessary_impl (Arg&& arg, std::true_type, std::false_type)
{
    return arg;
}

template <typename Param, typename Arg>
Param take_address_if_necessary_impl (Arg&& arg, std::false_type, std::true_type)
{
    return &arg;
}

template <typename Param, typename Arg>
Param take_address_if_necessary (Arg&& arg)
{
    return take_address_if_necessary_impl <Param> (
        arg,
        typename std::is_convertible <Arg, Param>::type {},
        typename std::is_convertible <typename std::add_pointer <Arg>::type, Param>::type {}
    );
}

template <typename Ret, typename... Params, typename... Args>
Ret call_special (Ret (*f) (Params...), Args&&... args)
{
    return f (take_address_if_necessary <Params, Args> (args)...);
}

template <typename... Params, typename... Args>
void call_special (void (*f) (Params...), Args&&... args)
{
    f (take_address_if_necessary <Params> (args)...);
}

void function (int* i, char* c)
{
    std::cout << *i << ' ' << *c << std::endl;
}

int main ()
{
    int i = 42;
    char c = '%';

    call_special (function, 1, 'f');
    call_special (function, &i, '?');
    call_special (function, &i, &c);
}

1 f
42 ?
42 %

.

: -, , , ++ :

void bar (int);
void bar (float);

call_special (bar, 3.0f); // Compiler error

, :

call_special <float> (bar, 3.0f); // Works

, , :

call_special ((void (*) (float))bar, 3.0f);

-, call_special . , , r, const ..

-, , , , . , , , :

void quux (long* i)
{
    if (i)
        std::cout << *i << std::endl;
    else
        std::cout << "(null)" << std::endl;
}

call_special (quux, NULL); // What does this print?

:

template <typename T>
T* foo (T&& t)
{
    return &t;
}

function (foo (3), foo ('7'));

, , , , . , , , , , , .

0

, , lvalue.

, , (sortof), rvalue.

, r lvalue. , rvalue , , , :

template<class T>
T& as_lvalue(T&& t){return t;}
template<class T>
void as_lvalue(T&)=delete;

:

function(&as_lvalue(1), &as_lvalue('v'));

as_lvaluerepresents an approximately opposite operation std::move, which could otherwise be called as_rvalue. This is not quite the opposite, because I did the conversion lvalue-to-lvalue generates an error.

Now unary &can be overloaded. Therefore, we can write:

template<class T>
T* addressof_temporary(T&& t) {
  return std::addressof( as_lvalue(std::forward<T>(t)) );
}

then call:

function(addressof_temporary(1), addressof_temporary('v'));

if paranoid.

0
source

Source: https://habr.com/ru/post/1583822/


All Articles