Why is std::generate accessible without namespace qualifier? - c++

Is it normal that this compiles fine?
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> buf;
generate(buf.begin(), buf.end(), []{ return 0; });
}
(Note the missing std:: in front of generate())
Is this behavior documented somewhere? Or did I stumble across a compiler or library bug? Which in my case would be GCC 5.3.0 and Clang 3.8.0 on Linux; both use libstdc++, so maybe library bug?

This is allowed, essentially because the arguments to generate are in std.
Code like
namespace Foo
{
struct B{};
void foo(const B&);
}
int main()
{
Foo::B b; /*Requires Foo::*/
foo(b); /*Does not require Foo:: as that is gleaned from the argument*/
}
is acceptable for similar reasons. We call it argument dependent lookup. See https://en.wikipedia.org/wiki/Argument-dependent_name_lookup

Related

varargs lambda gives illegal instruction - bug in clang or UB?

The following code gives Illegal instruction under clang, but works under gcc. Is it a bug in clang or is there some kind of UB?
#include <iostream>
#include <functional>
int main() {
std::function<void(const std::string&, const std::string&)> fn = [](...) { std::cout << "ok\n"; };
fn("a", "b");
}
As #Jarod42 commented, passing a non-trivial object to C-ellipsis has implementation defined semantics. Clang choose to abort in this case and it's normal.
To avoid the problem, one can use a lambda with a parameter pack like this:
#include <iostream>
#include <functional>
int main() {
std::function<void(const std::string&, const std::string&)> fn = [](auto&&...) { std::cout << "ok\n"; };
fn("a", "b");
}
It can be useful e.g. for default dummy callbacks:
constexpr auto DEFAULT_CALLBACK = [](auto&&...) {};

C++17 static and constexpr

I'm using the clang that comes bundled with Xcode 9.3, and I'm trying to understand whether the following result is an intentional part of C++17 changes:
#include <iostream>
template<typename T> struct Test {
static const int TEN;
};
template<typename T> constexpr int Test<T>::TEN = 10;
int main(int argc, const char * argv[]) {
std::cout << Test<int>::TEN << std::endl;
return 0;
}
When compiled with c++11 or c++14, this prints "10".
However, compiling this with c++17, this prints "0".
What's going on?
After posting this elsewhere, a clang developer acknowledged that this was a bug in clang-5 c++17 implementation, and that it is fixed in clang-6 onwards.
Thanks to tkausl for his initial comment that showed differing results in clang-6 and gcc, which led me to ask elsewhere.

chained copy elision with noncopyable types

Consider the following example:
#include <iostream>
#include <memory>
#include <boost/optional.hpp>
struct X {
boost::optional<std::unique_ptr<int>> foo(int i) {
std::unique_ptr<int> t(new int{i});
return t;
// every compiler works with:
// return std::unique_ptr<int>(new int{i});
}
};
struct Y {
X x;
boost::optional<std::unique_ptr<int>> bar(int i) {
return x.foo(i);
}
};
int main()
{
Y{}.bar(42);
}
I have two chained copy-elidable returns of a non-copyable object. gcc 5.2 compiles it fine. But neither gcc 4.8 nor clang 3.7 like it, due to actually trying to perform the copy. Which compiler is right? I'm assuming gcc intentionally changed to allow this behavior, which seems particularly useful for cases like this.

How do I std::bind with more than 4 placeholders in Visual C++?

I want to bind a member to store a function object outside of the class instance. Howeber, in VS2012 this only works up to placeholders::_4, then it starts popping up with errors. Take this for example:
#include <iostream>
#include <functional>
using namespace std;
using namespace std::placeholders;
class A
{
public:
int method(int a,int b,int c,int d,int e)
{
return a;
}
};
int main()
{
std::function<int (int,int,int,int,int)> obj;
A a;
// error: no instance of overloaded function "std::bind" matches the argument list
obj = std::bind(&A::method,&a,_1,_2,_3,_4,_5);
std::cout << obj(1,2,3,4,5);
return 0;
}
The above code compiles fine on GCC 4.7.2 but causes the above-mentioned error in Visual Studio 2012. Are there any workarounds, is this a bug in VC++ or am I doing something dodgy here?
Since Visual Studiio does not support variadic templates this is solved by a define.
You can set a define _VARIADIC_MAX to the amount of params you need. Do this in your projects settings to that it is set before any system headers are included.
But keep in mind that setting this value to a large number will increase compile times.
One alternative would be to use a lambda instead like this:
#include <iostream>
#include <functional>
using namespace std;
using namespace std::placeholders;
class A
{
public:
int method(int a, int b, int c, int d, int e)
{
return a;
}
};
int main()
{
std::function<int(int, int, int, int, int)> obj;
A a;
obj = [&a](int b, int c, int d, int e, int f){return a.method(b,c,d,e,f); };
std::cout << obj(1, 2, 3, 4, 5);
return 0;
}
edit: it seems like this won't work either without following #mkaes answer, since apparently the definition of the std::function depends on it.

Unnamed struct declaration inside for loop initialization statement

In one of the SO thread, I had seen a usage of unnamed struct acting as a placeholder for multiple variables of different types inside for loop:
For example:
for(struct {
int i;
double d;
char c;
} obj = { 1, 2.2, 'c' };
obj.i < 10;
++obj.i)
{
...
}
This compiles fine with g++.
Is this a standard C++03 syntax?
You can use an unnamed struct anywhere you can use a struct - the only difference is that it doesn't get a name that can be used somewhere else. You can declare a new type anywhere you can use a type, pretty much. It may not be particularly meaningful to do so in most places, but that's another matter.
I wouldn't exactly recommend this, other than in very special cases, but it's valid.
Below code will work in C++ (g++ 5.4.0).
http://rextester.com/ELWLF59792
//g++ 5.4.0
#include <iostream>
#include <stdio.h>
int main()
{
int i = 0;
for(struct st{ int a[9]; }t;i<3;i++)
printf("%d\n", t.a);
}
And below code will work in C (gcc 5.4.0).
//gcc 5.4.0
#include <stdio.h>
int main()
{
int i = 0;
struct st{ int a[9]; }t;
for(;i<3;i++)
printf("%d\n", t.a);
}