Search code examples
c++boostboost-python

How to use boost::python raw_function without getting warning C4267?


I'm using boost 1.82, and if I use boost::python::raw_function, I get warning C4267 even if I explicitly use size_t.

#include <boost/python.hpp>

#include <iostream>

boost::python::object Speak(boost::python::tuple args, boost::python::dict kwargs) {
    std::cout << "Test Speak!\n";
    return boost::python::object();
}

class Test {
public:
    Test() {}
};

void RegisterFuncs() {
    using namespace boost::python;

    class_<Test>("Test", no_init)
         .def("Speak", raw_function(&Speak, std::size_t{ 2 }));
}

int main()
{
    RegisterFuncs();
}

I get this warning:

Boost\include\boost-1_82\boost\python\raw_function.hpp(53,13): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
main.cpp(19,24): message : see reference to function template instantiation 'boost::python::api::object boost::python::raw_function<boost::python::api::object(__cdecl *)(boost::python::tuple,boost::python::dict)>(F,size_t)' being compiled
        with
        [
            F=boost::python::api::object (__cdecl *)(boost::python::tuple,boost::python::dict)
        ]

I could understand getting this warning if I was doing something like raw_function(&Speak, 2));, but I can't understand how this warning is here even if I explicitly pass in a size_t. This also gives the same warning:

std::size_t two{ 2 };

class_<Test>("Test", no_init)
     .def("Speak", raw_function(&Speak, two));

I can disable the warning with #pragma, but I'd rather understand how it's possible that this warning is present and not need to use #pragma.

I'm using Visual studio 2022 with /std:c++latest


Solution

  • There's nothing wrong in your code and nothing you can do to avoid the warning (besides changing the library code or #pragma the warning away). The problem is in raw_function itself:

    (boost/python/raw_function.hpp)

    template <class F>
    object raw_function(F f, std::size_t min_args = 0)
    {
        return detail::make_raw_function(
            objects::py_function(
                detail::raw_dispatcher<F>(f)
              , mpl::vector1<PyObject*>()
              , min_args
              , (std::numeric_limits<unsigned>::max)()
            )
        );
    }
    

    min_args, which is the size_t you pass in your (correct) code, is passed to py_function constructor accepting an int in that position (min_arity):

    (boost/python/object/py_function.hpp)

    struct py_function {
        // ...
        template <class Caller, class Sig>
            py_function(Caller const& caller, Sig, int min_arity, int max_arity = 0)
              : m_impl(new full_py_function_impl<Caller, Sig>(caller, min_arity, max_arity))
            {}
        // ...
    }
    

    The links to files above are for Boost 1.82.0 which you use, but for current version (1.84.0) the situation is the same.

    This seems to be not the only problem with mismatch of integral types in Boost.Python, e.g. there's this issue still open on GitHub.