On 07/29/2016 12:29 PM, Alex Rousskov wrote:
> If possible, we should avoid macros and should learn how to use C++11
> correctly. In general, it makes little sense to suffer the pains of
> switching to C++11 and then use macros for things C++11 is supposed to
> provide or support natively.
>
> However, in this specific case, some macros may be unavoidable or even a
> good idea because we are also dealing with C libraries that we cannot
> convert to C++11. Please give me a few hours to think whether there is a
> macro-free solution available.
I found two macro-free ways to do this. The so called "smart" one does
most of the work for us, but requires repeating the function name twice,
once with decltype() and once without:
typedef HardFun<decltype(BIO_vfree), &BIO_vfree> BIO_Deleter;
A simpler implementation is arguably more verbose/repetitive:
typedef HardFun<void, BIO*, &BIO_vfree> BIO_Deleter;
For comparison, the macro-based approach yields:
CtoDeleter(BIO, BIO_vfree); // declares BIO_Deleter
And the current buggy trunk code is equivalent to this perfection:
typedef std::function<decltype(BIO_free)> BIO_Deleter;
Since the smarter implementation does not give a perfect result despite
its tricks/complexity, I suggest going with the simpler one. The macros
do not seem to be necessary (and HardFun offers better reuse
possibilities than a macro if we need more hard-coded functors).
I have attached sketches for the smart and simple implementation. They
compile and run without throwing, but I have not tested beyond that (but
the same kind of sketch with the trunk-equivalent code did throw).
HTH,
Alex.
#include <functional>
#include <memory>
/* for testing without OpenSSL */
struct BIO {};
extern "C" { void BIO_vfree(BIO *bio) { delete bio; } };
/* for extracting result and argument types from a unary function type */
template <typename T>
struct function_traits;
template <typename ReturnType, typename ArgType>
struct function_traits<ReturnType(ArgType)>
{
typedef ReturnType result_type;
typedef ArgType arg_type;
};
/* a functor that calls a hard-coded unary function */
template <class FunType, FunType *fun>
struct HardFun {
typename function_traits<FunType>::result_type
operator()(typename function_traits<FunType>::arg_type arg) { fun(arg); }
};
/* usage example */
typedef HardFun<decltype(BIO_vfree), &BIO_vfree> BIO_Deleter;
typedef std::unique_ptr<BIO, BIO_Deleter> BIO_Pointer;
int main() {
BIO_Pointer bio(new BIO);
return 0;
}
#include <functional>
#include <memory>
/* for testing without OpenSSL */
struct BIO {};
extern "C" { void BIO_vfree(BIO *bio) { delete bio; } };
/* a functor that calls a hard-coded unary function */
template <class ReturnType, class ArgType, ReturnType (*fun)(ArgType)>
struct HardFun {
ReturnType operator()(ArgType arg) { fun(arg); }
};
/* usage example */
typedef HardFun<void, BIO*, &BIO_vfree> BIO_Deleter;
typedef std::unique_ptr<BIO, BIO_Deleter> BIO_Pointer;
int main() {
BIO_Pointer bio(new BIO);
return 0;
}
_______________________________________________
squid-dev mailing list
[email protected]
http://lists.squid-cache.org/listinfo/squid-dev