Creating a function alias - c++

EDIT: This question was originally titled "Using std::bind to create inline function," but that's not really what I'm after: I just want a simple way to alias functions.
I would like to expose std::chrono::high_resolution_clock::now as a standalone function. That is, I would like to do the following:
auto current_time = std::bind(std::chrono::high_resolution_clock::now);
Unfortunately, since this is in a header file, it results in multiple definitions of current_time at link-time. Is there a way to return an inline function from std::bind?

Here's what I do if I want to create a simple function alias
constexpr auto &&now = std::chrono::high_resolution_clock::now;
and if I want to create a full wrapper alias that will be inlined
template<typename ... Args>
inline constexpr auto now(Args &&... args) -> decltype(std::chrono::high_resolution_clock::now(std::forward<Args>(args)...)){
return std::chrono::high_resolution_clock::now(std::forward<Args>(args)...);
}
The reason why I use a universal reference auto&& in the alias definition is because of the possibility of addressof(now) == addressof(std::chrono::high_resolution_clock::now).
On my system with G++ 4.9.2 running this:
constexpr auto &&now_ref = std::chrono::high_resolution_clock::now;
constexpr auto now_var = std::chrono::high_resolution_clock::now;
template<typename ... Args>
inline constexpr auto now_wrapper(Args &&... args)
-> decltype(std::chrono::high_resolution_clock::now(std::forward<Args>(args)...)){
return std::chrono::high_resolution_clock::now(std::forward<Args>(args)...);
}
int main(int argc, char *argv[]){
std::cout << std::hex << std::showbase;
std::cout << (uintptr_t)std::addressof(std::chrono::high_resolution_clock::now) << '\n';
std::cout << (uintptr_t)std::addressof(now_wrapper<>) << '\n';
std::cout << (uintptr_t)std::addressof(now_var) << '\n';
std::cout << (uintptr_t)std::addressof(now_ref) << '\n';
}
I get the following results:
0x4007c0
0x400a50
0x400ae8
0x4007c0
Showing that only the auto&& is actually a direct alias of the function, whereas all other methods have some level of indirection. (although, after compilation they may be replaced by inlined function calls. maybe.)

I don't think there is anyway to do this as bind is not constexpr.
Also lambdas are not constexpr-able.
Edit: there is this trick to make a constexpr-like lambda http://pfultz2.com/blog/2014/09/02/static-lambda/

Adding another answer 'cause it takes a very different tack to what you want.
std::bind isn't necessary in this case, because no 'binding' is happening.
However I feel this could lead to some confusing problems down the line, since current_time isn't really an alias in the same way that using delcarations are.
#include <iostream>
#include <chrono>
using namespace std;
auto constexpr current_time = std::chrono::high_resolution_clock::now;
int main() {
auto now = current_time();
cout << std::chrono::system_clock::to_time_t(now) << endl;
return 0;
}

Using GCC it is possible to create a "function alias", but only for functions which are defined in the same translation unit and for which you know the mangled name, so it's not possible to do reliably for std::chrono::high_resolution_clock::now()
See the alias attribute at https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

Keep it simple.
const auto current_time = std::chrono::high_resolution_clock::now;

Related

Retrieve the name of the pointed-to function from a function pointer template argument at compile time [duplicate]

I have a function wrapper class im trying to work on.
I want to be able to show the name of the function that is passed into the template.
template<auto Func>
struct FuncWrapper final {
FuncWrapper() {
StrFuncName = typeid(Func).name();
std::cout << StrFuncName << std::endl;
}
template<typename... Args>
auto operator()(Args&&... args) const { }
std::string StrFuncName;
};
void Function() { }
FuncWrapper<Function> wrapper;
This is not possible with standard C++. Demangling the typeid won't help either because you're only going to get the name of the type of the function, not the name you actually gave the function.
The closest you can get is the predefined __func__ constant, but that only exists inside the scope of the function you'd want to get the name of anyways.
void foo()
{
std::cout << __func__; // will print "foo"
}
It's not possible in standard C++, but some compiler/libraries may have a way to work around that.
For example, gcc's libstdc++ has an extension which could demangle a typeid value:
#include <cxxabi.h>
std::cout << typeid(type).name() << " -> " abi::__cxa_demangle(typeid(type).name(), 0, 0, 0) << std::endl
It is possible to implement a version of this portably using typeid:
template<auto&>
struct symbol;
template<auto &S>
const char* name() {return typeid(symbol<S>).name();}
The name is of course *implementation-defined; in practice, it may or may not require demangling (in addition to stripping the symbol<…> decoration).
There is the alternative approach of using commonplace compiler extensions:
template<auto &S>
const char* name() {return __PRETTY_FUNCTION__;}
This too has to have the const char * name<…>() stripped.
Getting a function’s name from a non-constant-expression pointer to it is also possible but only via the use of a library that interprets the symbol table and/or debugging information.

Using `static` keyword with Structured Binding

I'm trying to use C++17 structured binding to return a pair of values and I want those values to be both static and const so that they are computed the first time the function they're in is called and then they maintain their uneditable values for the lifetime of the program. However when I do this I get the error: a structured binding cannot declare an explicit storage class error and I'm not sure why or how to fix it. A minimum working example is below.
#include <iostream>
#include <utility>
static const std::pair<double, double> pairReturn()
{
return {3,4};
}
int main()
{
static const auto [a, b] = pairReturn();
std::cout << a << std::endl;
std::cout << b << std::endl;
return 0;
}
The error is a bit confusing, but structured binding to static variables is just not supported with c++17. Either use a different solution, or c++2a. A different solution could just be an additional line:
static std::pair pr = pairReturn();
auto &[a, b] = pr;

Parameter passing bug in Boost.Log

I've been experimenting with Boost.Log for the first time and quickly ran into problems. The following simple code does not work correctly for me
#include <boost/log/common.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/sources/logger.hpp>
namespace logging = boost::log;
namespace src = boost::log::sources;
BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(my_logger, src::logger)
static void init()
{
logging::add_file_log("test.log");
}
int main(int, char* [])
{
init();
BOOST_LOG(my_logger::get()) << "hello, world";
return 0;
}
The problem is that the log is saved in a file called 00000.log instead of the test.log requested. Investigating a little it seems the problem is that the "test.log" argument isn't being passed down to Boost.Log's internal classes and when this happens a default file pattern of "%N.log" is used which results in the 00000.log file name that I see.
Boost.Log uses Boost.Parameter to implement named parameters so I tried the being explicit about the parameter I'm using
logging::add_file_log(logging::keywords::file_name = "test.log");
This fails in the same way. Interestingly however if I pass two parameters the code works correctly, e.g.
logging::add_file_log(logging::keywords::file_name = "test.log",
logging::keywords::auto_flush = true);
I've not been able to determine where the fault lies, it could be Boost.Log, Boost.Parameter, or a compiler bug. What I'm looking for is some explanation of the nature of the bug. I can work around this particular issue as shown above, but if there's something fundamentally wrong with parameter passing in Boost.Log that's pretty serious. If anyone has any experience with this bug or if they could try the above code on their platform I'd appreciate it.
I'm using Boost 1.74.0 and Visual Studio 2019 and C++17. I'm using static Boost libraries which are linked statically with the C++ runtime.
You're exactly right. It is a bug.
Reducing it all the way:
std::cerr << (kw::file_name = "first.log")[kw::file_name | boost::filesystem::path()] << std::endl;
Prints "". A slightly more informative test-bed:
Live On Coliru
#include <boost/log/utility/setup/file.hpp>
#include <iostream>
int main() {
namespace kw = boost::log::keywords;
auto test = [](auto params) {
std::cerr << "Non-defaulted: " << params[kw::file_name] << std::endl;
std::cerr << "Defaulted: " << params[kw::file_name | boost::filesystem::path()] << std::endl;
};
test((kw::file_name = "aaa"));
test((kw::file_name = "bbb", kw::auto_flush = false));
test((kw::auto_flush = false, kw::file_name = "ccc"));
}
Prints
Non-defaulted: aaa
Defaulted: ""
Non-defaulted: bbb
Defaulted: bbb
Non-defaulted: ccc
Defaulted: ccc
Clearly, the | filesystem::path() syntax is throwing a wrench. And it only manifests in the single-argument case.
Cause/fix?
The correct flow goes into `arglist::operator[]:
template <typename Default>
inline BOOST_CONSTEXPR reference
operator[](
::boost::parameter::aux::default_r_<key_type,Default> const& d
) const
{
return this->get_default(d, _holds_maybe());
}
Into
// Helpers that handle the case when TaggedArg is empty<T>.
template <typename D>
inline BOOST_CONSTEXPR reference
#if defined(BOOST_PARAMETER_CAN_USE_MP11)
get_default(D const&, ::boost::mp11::mp_false) const
#else
get_default(D const&, ::boost::mpl::false_) const
#endif
{
return this->arg.get_value();
}
Into `tagged_arg::
inline BOOST_CONSTEXPR reference get_value() const
{
return this->value;
}
The malfunctioning case goes into
template <typename KW, typename Default>
inline BOOST_CONSTEXPR Default&&
operator[](
::boost::parameter::aux::default_r_<KW,Default> const& x
) const
{
return ::std::forward<Default>(x.value);
}
This is at once incorrect as KW == boost::log::v2_mt_posix::keywords::tag::file_name, so one would have expected this overload to have been taken:
template <typename Default>
inline BOOST_CONSTEXPR reference
operator[](
::boost::parameter::aux::default_r_<key_type,Default> const&
) const
{
return this->get_value();
}
But. That's only defined for tagged_argument_rref, looks like that was an oversight (the overloads for default_<> are both there, for comparison).
Checking The Hypothesis
If the problem is specific for default_r_<> then it should be gone with a default value that is an lvalue:
auto args = (kw::file_name = "aaa");
path lvalue;
std::cerr << "default_r_<>: " << args[kw::file_name | path()] << "\n";
std::cerr << "default_<>: " << args[kw::file_name | lvalue] << "\n";
Which indeed prints
default_r_<>: ""
default_<>: aaa
Fix
It stands to reason that the overload for default_r_<keyword_type, ...> needs to be added for tagged_argument. Indeed this works (on my machine).
I was going to create a PR, so I opened issue #104. But when forking is turns out that there is already a fix in develop:
tree fff523c8fe0a3de1c1378a2292840f217cc4d6d3
parent 0f548424a5f966fadfa7a21a759c835729cbc009
author Andrey Semashev <andrey.semashev#gmail.com> Sun Mar 15 18:13:07 2020 +0300
committer Andrey Semashev <andrey.semashev#gmail.com> Sun Mar 15 18:20:34 2020 +0300
Fix argument value selection with an rvalue default.
In C++11 mode, when named parameter pack was a single tagged argument,
parameter value was not extracted when an rvalue default value was
provided by the user (instead, the default value was returned). This
commit adds a missing overload for default_r_, which returns the parameter
value.
Fixes https://github.com/boostorg/parameter/issues/97.
So, yeah look like the fix is months old and the issue duplicates #97.

init-capture for rvalue reference in Visual Studio 2013

I want use .net's System.Threading.Tasks.Task.ContinueWith in C++, so I write the following function..
#include <iostream>
#include <functional>
#include <future>
template <typename Func, typename Ret>
auto continue_with(std::future<Ret> &&fu, Func func)
-> std::future<decltype(func(fu.get()))>
{
return std::async(
[fu = std::move(fu), func]() mutable { return func(fu.get()); }
);
}
template <typename Func>
auto continue_with(std::future<void> &&fu, Func func)
-> std::future<decltype(func())>
{
return std::async(
[fu = std::move(fu), func]() mutable { fu.get(); return func(); }
);
}
int main()
{
std::future<void> fu = std::async([]{ std::cout << "fu" << std::endl; });
std::future<void> fu2 = continue_with(
std::move(fu),
[]{ std::cout << "fu2" << std::endl; }
);
fu2.get();
std::cout << "fu continue complete" << std::endl;
std::future<int> retfu = std::async([]{ std::cout << "retfu" << std::endl; return 3; });
std::future<int> retfu2 = continue_with(
std::move(retfu),
[](int result){ std::cout << "retfu2 " << result << std::endl; return result + 1; }
);
int ret = retfu2.get();
std::cout << "retfu continue complete : " << ret << std::endl;
std::cin.get();
}
This code works on gcc 4.8.2 with -std=c++1y. (I don't know why, but it works with -std=c++11, too)
But it doesn't work on VC++ 2013. I guess it's because init-capture, a C++14 feature. How can I run this code with VC++ 2013?
(I want to use lambda, so please don't tell me "use just function-object struct!")
(I tried Move capture in lambda, but it doesn't work..)
(I'll appreciate if you not only answer my question but also imporve my code)
Unfortunately, this feature was not present yet in Visual Studio 2013. It was released in June 2014 with the Visual Studio "14" CTP (community tech preview, which is alpha-quality and not ready for production code). To quote:
Here are the improvements for Visual C++:
Generalized lambda capture: You can assign the result of evaluating an
expression to a variable in the capture clause of a lambda. This
allows an instance of a move-only type to be captured by value.
As was pointed out in the comments: as a work-around for Visual Studio 2013, you can make your own function object with local variables initialized through the constructor. Yes, this sucks, but it has been the standard trick before lambdas were invented. It was also the case with polymorphic lambdas until they were supported (workaround: function object with templated operator()) and currently with the currently disallowed constexpr lambdas (workaround: constexpr function object of literal type).
2 other options exist, using std::bind and writing a move on copy wrapper.
so you could do
return std::async(std::bind(
[func](std::future<void> & fu) mutable { fu.get(); return func(); },
std::move(fu)
);
The move on copy wrapper I can just point you to How to capture std::unique_ptr "by move" for a lambda in std::for_each

Negate boost is_directory in std algorithm

boost::filesystem::recursive_directory_iterator end, begin(directory);
auto num_of_files=std::count_if(begin, end,
std::not1(boost::filesystem::is_directory)));
I am trying to negate the function is_directory on the above directory iterator but am hitting a brick wall. I have tried specifying the template for not1 as bool(*)(const boost::filesystem::path&) and tried static casting the function both without success.
I know I can resort to a lamdba but this is cleaner if it works.
Thanks
std::not1 needs a function object as its argument. This function object can be obtained with std::ptr_fun, so this should work:
auto num_of_files=std::count_if(begin, end,
std::not1(std::ptr_fun((bool(*)(const boost::filesystem::path&))boost::filesystem::is_directory)));
(the number of parentheses is probably incorrect). BTW, you need the cast because is_directory is an overloaded function.
However, since you tag you question c++11, you could use lambdas:
auto num_of_files=std::count_if(begin, end, [](const boost::filesystem::path& p) { return !boost::filesystem::is_directory(p); });
not1 accepts an instance of functor class, which should be an Adaptable Predicate (i.e. with typedefs for return value etc.), while you are trying to feed it with a function pointer. So you need to wrap it in a functor and ptr_fun might help.
Perhaps this would work (assume using namespace std; using namespace boost;):
auto num_of_files=count_if(begin, end, not1(ptr_fun(filesystem::is_directory)));
You need ptr_fun,
this rather elaborate illustration should print 1 three times: (see also http://ideone.com/C5HTR)
#include <functional>
#include <string>
#include <algorithm>
#include <iostream>
bool pred(const std::string& s)
{
return s.size() % 2;
}
int main()
{
std::string data[] = { "hello", "world!" };
std::cout << std::count_if(data, data+2,
pred) << std::endl;
std::cout << std::count_if(data, data+2,
std::ptr_fun(pred) ) << std::endl;
std::cout << std::count_if(data, data+2,
std::not1(std::ptr_fun(pred))) << std::endl;
return 0;
}