开发者

In C++ can I reset the function pointer for an operator?

开发者 https://www.devze.com 2023-03-23 21:59 出处:网络
In C++ can I reset the function pointer for an operator? In particular I want to set the member开发者_高级运维 function operator[] to use (or not use) bounds checking. I tried this with no luck:

In C++ can I reset the function pointer for an operator?

In particular I want to set the member开发者_高级运维 function operator[] to use (or not use) bounds checking. I tried this with no luck:

Is this even possible? If so, Can anyone correct the syntax?

in MyArrayClass.h:

class MyArrayClass {
public:
    bool CheckArrayBounds;
    float BoundsCheck(int i) {
        if (i<_size) 
            return _data[i]; 
        return TCpx(_INVALID); 
    }
    float NoBoundsCheck(int i) {
        return _data[i]; 
    }
    void UseBoundsCheck(bool State) {
        if (State) {
            float (operator[]) = &MyArrayClass::BoundsCheck;
        } else {
            float (operator[]) = &MyArrayClass::NoBoundsCheck;
        }
        CheckArrayBounds = State;
    }
    float operator[](int i) { return _data[i]; };
};


This is not possible. Semantically speaking, member functions are not function pointers (although they may be implemented that way under the hood).

You could perform the check on State inside operator[] (), or use a proxy object.


You cannot change operator for particular object instance in runtime because member functions are stored separately from object attributes and are the same for all object instances. And they are stored in write-protected memory segment. Or could even be inlined by the compiler.

Still you can check for state inside of the operator[] implementation.

Also you can create attribute at and replace operator.

class MyArrayClass {
public:
    float (MyArrayClass::*at)(int i);
    float BoundsCheck(int i);
    float NoBoundsCheck(int i); {
    void UseBoundsCheck(bool State) {
        at = (State)? &MyArrayClass::BoundsCheck : &MyArrayClass::NoBoundsCheck;
    }
};

Usage:

MyArrayClass a;
a.at( 1 );


No.

Methods (and operators which are just syntactic sugar for methods/functions) are defined at compile time not run time.


C++ isn't the right kind of language for this, unfortunately. You need a much more powerful type system.

Note that even if you could, you'd probably slow your program down: a integer comparison is much more expensive that a function call through a pointer. Especially since your CPU can branch predict: it'll start running code as if it passed the check, and if it ends up failing it can ditch whatever it was doing.

But note your compiler is smart. For example, if we have this:

#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <iterator>
#include <vector>

void process(std::vector<int>& data)
{
    for (unsigned i = 0; i < data.size(); ++i)
    {
        int v = data.at(i);
        std::cout << v << std::endl;
    }
}

int main()
{
    try
    {
        std::vector<int> data;
        std::generate_n(std::back_inserter(data), std::rand() + 1, std::rand);

        process(data);
    }
    catch (...)
    {
        std::cerr << "nope.avi" << std::endl;
    }
}

And if we compile with g++ -O3, there is no bounds checking code. Indeed, the compiler has deduced that the check inside at() will never pass (which then throws), so it stripped away that code. So you can leave the bounds checking in and your compiler can still strip it away. Note, though, that any more complex cases may make it too hard for the compiler to prove, so you'll pay for it.

These are the kind of optimizations you could guarantee with a more expressive type system, but the compiler can do them anyway. I don't know about MSVC; it tends not to be as smart, but you can check.

Your best bet is to go the std::vector<> route: provide an unchecked operator[] and a checked at(). Let the user of your class decide if they need checks or not.


Functions and member functions are effectively constant an immutable, and it is not possible to change them at runtime. However, there's a kind of half-way house to what you are trying to do, and you were almost there in your posted code.

What you can do is define a pointer to a member function, and then alter the pointer value at runtime depending on whether you want bounds checking active or not.

class MyArrayClass {
public:
    typedef float (MyArrayClass::*AccessFn)(int i);
    AccessFn Access;
    bool CheckArrayBounds;

    float BoundsCheck(int i) {
        if (i<_size)
            return _data[i];
        return TCpx(_INVALID);
    }
    float NoBoundsCheck(int i) {
        return _data[i];
    }

    MyArrayClass() { UseBoundsCheck(false); }

    void UseBoundsCheck(bool State) {
        if (State) {
            Access = &MyArrayClass::BoundsCheck;
        } else {
            Access = &MyArrayClass::NoBoundsCheck;
        }
        CheckArrayBounds = State;
    }
    float operator[](int i) { return (this->*Access)(i); }
};

This is the closest way of doing what you've requested that I can think of.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号