The following code for a simple hash function won't compile
#include <cstddef>
#include <functional>
namespace {
struct Foo {
long i;
};
}
namespace std {
template<> struct hash<::Foo> {
size_t operator()(::Foo foo) const {
return hash<decltype(foo.i)>(foo.i);
}
};
}
My 4.8.5 g++ compiler emits these messages:
$ g++ -std=c++11 a.cpp
a.cpp: In member function ‘std::size_t std::hash<{anonymous}::Foo>::operator()({anonymous}::Foo) const’:
a.cpp:13:47: error: no matching function for call to ‘std::hash<long int>::hash(long int&)’
return hash<decltype(foo.i)>(foo.i);
^
a.cpp:13:47: note: candidates are:
In file included from /usr/include/c++/4.8.2/bits/basic_string.h:3033:0,
from /usr/include/c++/4.8.2/string:52,
from /usr/include/c++/4.8.2/stdexcept:39,
from /usr/include/c++/4.8.2/array:38,
from /usr/include/c++/4.8.2/tuple:39,
from /usr/include/c++/4.8.2/functional:55,
from a.cpp:2:
/usr/include/c++/4.8.2/bits/functional_hash.h:107:3: note: constexpr std::hash<long int>::hash()
_Cxx_hashtable_define_trivial_hash(long)
^
/usr/include/c++/4.8.2/bits/functional_hash.h:107:3: note: candidate expects 0 arguments, 1 provided
/usr/include/c++/4.8.2/bits/functional_hash.h:107:3: note: constexpr std::hash<long int>::hash(const std::hash<long int>&)
/usr/include/c++/4.8.2/bits/functional_hash.h:107:3: note: no known conversion for argument 1 from ‘long int’ to ‘const std::hash<long int>&’
/usr/include/c++/4.8.2/bits/functional_hash.h:107:3: note: constexpr std::hash<long int>::hash(std::hash<long int>&&)
/usr/include/c++/4.8.2/bits/functional_hash.h:107:3: note: no known conversion for argument 1 from ‘long int’ to ‘std::hash<long int>&&’
$ fg
The problem appears to be the call-by-reference in the first error message but I don't understand why or how to fix it.
You are missing a set of parentheses in
return hash<decltype(foo.i)>(foo.i);
In the above you are trying to construct a std::hash, not call its operator(). You need
return hash<decltype(foo.i)>()(foo.i);
// or
return hash<decltype(foo.i)>{}(foo.i);
where the empty set of parentheses/curly braces constructs the hash object, and the second set calls its operator()
Related
I have a construct similar to the following in my code.
#include <optional>
struct C {
struct C2 {
bool b { false };
};
std::optional<C2> oc2;
};
int main(int argc, char** argv) {
C c;
c.oc2.emplace(); // clang error!
}
It's an std::optional object inside of a class that I want to initialize via its default constructor. The above code compiles fine in GCC 9. But Clang 9 fails with the following error:
% clang++-9 -std=c++17 -o main main.cpp
main.cpp:13:11: error: no matching member function for call to 'emplace'
c.oc2.emplace();
~~~~~~^~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/optional:845:2: note: candidate template ignored: requirement 'is_constructible_v<C::C2>' was not satisfied [with _Args = <>]
emplace(_Args&&... __args)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/optional:855:2: note: candidate function template not viable: requires at least argument '__il', but no arguments were provided
emplace(initializer_list<_Up> __il, _Args&&... __args)
^
1 error generated.
Is this a Clang bug or is there a better way to initialize an optional value in that case?
Consider the following example:
#include <array>
template <typename T>
struct A {
A() {}
};
typedef A<int> B;
struct S {
std::array<B, 1> b;
S() : b{{B()}} {}
};
int main() {
S s;
}
when trying to compile it with g++ 4.6.3 and -std=c++0x I get this error:
test.cc: In constructor ‘S::S()’:
test.cc:13:16: error: no matching function for call to ‘std::array<A<int>, 1ul>::array(<brace-enclosed initializer list>)’
test.cc:13:16: note: candidates are:
/usr/include/c++/4.6/array:60:12: note: std::array<A<int>, 1ul>::array()
/usr/include/c++/4.6/array:60:12: note: candidate expects 0 arguments, 1 provided
/usr/include/c++/4.6/array:60:12: note: constexpr std::array<A<int>, 1ul>::array(const std::array<A<int>, 1ul>&)
/usr/include/c++/4.6/array:60:12: note: no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘const std::array<A<int>, 1ul>&’
/usr/include/c++/4.6/array:60:12: note: constexpr std::array<A<int>, 1ul>::array(std::array<A<int>, 1ul>&&)
/usr/include/c++/4.6/array:60:12: note: no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘std::array<A<int>, 1ul>&&’
However, the same brace initialization works when defining a variable:
std::array<B, 1> b{{B()}};
Is it because this particular version of gcc doesn't fully implement C++11 or am I missing something and the first example is not correct?
Is it because this particular version of gcc doesn't fully implement C++11
Most probably yes. GCC 4.6 is pretty outdated.
or am I missing something and the first example is not correct?
Regarding c++11 syntax your example is fine. It compiles at colliru without errors or warnings.
I am currently using the cpprest API found at https://casablanca.codeplex.com/ for a simple RESTful API project.
This popular library uses Microsoft's PPLX framework to facilitate the async tasks.
I am currently encountering an issue in which code does not compile when a function returns an object of type pplx::task<SomeObj> and SomeObj has no default constructor. My understanding is that this code should be a valid as no default objects should be created.
Is there an error in my code or is this a bug?
Example Code:
#include <vector>
#include <string>
#include <cpprest/http_client.h>
class SomeSubObj {
public:
int a,b,c;
SomeSubObj(int a, int b, int c): a(a), b(b), c(c){}
};
class SomeObj {
public:
std::vector<SomeSubObj> subObjs;
SomeObj(std::string json){
// Populate from JSON...
subObjs.push_back(SomeSubObj(1,1,1));
subObjs.push_back(SomeSubObj(2,2,2));
subObjs.push_back(SomeSubObj(3,3,3));
}
};
pplx::task<SomeObj> doSomething(){
return pplx::task<std::string>([]() {
// Make a call out and get some json...
return std::string("{...}");
}).then([](std::string x) {
// Return a transformed object
return SomeObj("...");
});
}
int main()
{
doSomething();
return 0;
}
I am currently receiving the following output:
g++ -std=c++0x -Iboost_thread-mt -Iboost_atomic -Iboost_system -Icpprest -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/Bug.d" -MT"src/Bug.d" -o "src/Bug.o" "../src/Bug.cpp"
In file included from ../src/Bug.cpp:4:
In file included from /usr/local/include/cpprest/http_client.h:44:
/usr/local/include/pplx/pplxtasks.h:2404:9: error: call to implicitly-deleted default constructor of '_ResultHolder<SomeObj>'
_Task_impl(_CancellationTokenState * _Ct, scheduler_ptr _Scheduler_arg)
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:2096:15: note: in instantiation of member function 'pplx::details::_Task_impl<SomeObj>::_Task_impl' requested here
__second_(_VSTD::forward<_Args2>(get<_I2>(__second_args))...)
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:2359:15: note: in instantiation of function template specialization 'std::__1::__libcpp_compressed_pair_imp<std::__1::allocator<pplx::details::_Task_impl<SomeObj> >, pplx::details::_Task_impl<SomeObj>, 1>::__libcpp_compressed_pair_imp<std::__1::allocator<pplx::details::_Task_impl<SomeObj> > &, pplx::details::_CancellationTokenState *&, pplx::scheduler_ptr &, 0, 0, 1>' requested here
: base(__pc, _VSTD::move(__first_args), _VSTD::move(__second_args),
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3697:16: note: in instantiation of function template specialization 'std::__1::__compressed_pair<std::__1::allocator<pplx::details::_Task_impl<SomeObj> >, pplx::details::_Task_impl<SomeObj> >::__compressed_pair<std::__1::allocator<pplx::details::_Task_impl<SomeObj> > &, pplx::details::_CancellationTokenState *&, pplx::scheduler_ptr &>' requested here
: __data_(piecewise_construct, _VSTD::forward_as_tuple(__a),
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:4271:26: note: in instantiation of function template specialization 'std::__1::__shared_ptr_emplace<pplx::details::_Task_impl<SomeObj>, std::__1::allocator<pplx::details::_Task_impl<SomeObj> > >::__shared_ptr_emplace<pplx::details::_CancellationTokenState *&, pplx::scheduler_ptr &>' requested here
::new(__hold2.get()) _CntrlBlk(__a2, _VSTD::forward<_Args>(__args)...);
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:4630:29: note: in instantiation of function template specialization 'std::__1::shared_ptr<pplx::details::_Task_impl<SomeObj> >::make_shared<pplx::details::_CancellationTokenState *&, pplx::scheduler_ptr &>' requested here
return shared_ptr<_Tp>::make_shared(_VSTD::forward<_Args>(__args)...);
^
/usr/local/include/pplx/pplxtasks.h:1429:103: note: (skipping 1 context in backtrace; use -ftemplate-backtrace-limit=0 to see all)
static _Type _Make(_CancellationTokenState * _Ct, scheduler_ptr _Scheduler_arg) { return std::make_shared<_Task_impl<_ReturnType>>(_Ct, _Scheduler_arg); }
^
/usr/local/include/pplx/pplxtasks.h:3623:52: note: in instantiation of member function 'pplx::details::_Task_ptr<SomeObj>::_Make' requested here
_M_Impl = details::_Task_ptr<_ReturnType>::_Make(_Ct, _Scheduler);
^
/usr/local/include/pplx/pplxtasks.h:4138:27: note: in instantiation of member function 'pplx::task<SomeObj>::_CreateImpl' requested here
_ContinuationTask._CreateImpl(_PTokenState, _Scheduler);
^
/usr/local/include/pplx/pplxtasks.h:4101:16: note: in instantiation of function template specialization 'pplx::task<std::__1::basic_string<char> >::_ThenImpl<std::__1::basic_string<char>, <lambda at ../src/Bug.cpp:27:10> >' requested here
return _ThenImpl<_InternalReturnType, _Function>(_Func, _PTokenState, _TaskOptions.get_continuation_context(), _Scheduler, _CreationStack);
^
/usr/local/include/pplx/pplxtasks.h:3424:16: note: in instantiation of function template specialization 'pplx::task<std::__1::basic_string<char> >::_ThenImpl<std::__1::basic_string<char>, <lambda at ../src/Bug.cpp:27:10> >' requested here
return _ThenImpl<_ReturnType, _Function>(_Func, _TaskOptions);
^
../src/Bug.cpp:27:5: note: in instantiation of function template specialization 'pplx::task<std::__1::basic_string<char> >::then<<lambda at ../src/Bug.cpp:27:10> >' requested here
}).then([](std::string x) {
^
/usr/local/include/pplx/pplxtasks.h:844:15: note: default constructor of '_ResultHolder<SomeObj>' is implicitly deleted because field '_Result' has no default constructor
_Type _Result;
^
1 error generated.
make: *** [src/Bug.o] Error 1
I have this simplified code consisting of a class with a static function, which is stored in map:
#include <iostream>
#include <functional>
#include <map>
class A {
public:
static void f(const std::string &s) { std::cout << s; }
};
std::map<std::string, std::function<void(std::string const &)>> fs;
int main() {
fs["f"] = &A::f;
fs["f"]("hello");
}
This prints the expected hello.
The problem occurs if I overload f() with:
static void f(const std::string &s, int c) { while(c-->0) { std::cout << s; } }
This results in the error:
error: no viable overloaded '='
fs["f"] = &A::f;
~~~~~~~ ^ ~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/functional:2241:7: note: candidate function not viable: no overload of 'f' matching 'const std::function<void (const std::basic_string<char> &)>' for 1st argument
operator=(const function& __x)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/functional:2259:7: note: candidate function not viable: no overload of 'f' matching 'std::function<void (const std::basic_string<char> &)>' for 1st argument
operator=(function&& __x)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/functional:2273:7: note: candidate function not viable: no overload of 'f' matching 'nullptr_t' for 1st argument
operator=(nullptr_t)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/functional:2302:2: note: candidate template ignored: couldn't infer template argument '_Functor'
operator=(_Functor&& __f)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/functional:2311:2: note: candidate template ignored: couldn't infer template argument '_Functor'
operator=(reference_wrapper<_Functor> __f) noexcept
^
However, calling both functions works:
A::f("hello ");
A::f("echo ", 3);
So, my question are:
Why this code not compiling even though the operator= seems to exist and function if I don't overload f()?
How can I get it to work without giving both functions different names?
Why this code not compiling even though the operator= seems to exist
and function if I don't overload f()?
Because the compiler doesn't know which overload to choose. How could he? There is no criterion upon which he can decide which one is suited better. Every std::function allows arbitrary function objects to be assigned and doesn't check any signatures. If you wanted to save only function pointers of this particular signature you should have declared the map appropriately.
How can I get it to work without giving both functions different
names?
As already mentioned it works by casting the expression to a function pointer of the specific type.
fs["f"] = static_cast<void(*)(std::string const&)>( &A::f );
This way no ambiguities arise; There is exactly one overload that can be casted to this function to pointer type. If this appears more often then a typedef could be feasible.
Or a little helper class template:
template <typename... Exact>
struct funptr
{
template <typename R>
constexpr auto operator()(R(*p)(Exact...)) -> decltype(p)
{ return p; }
};
fs["f"] = funptr<std::string const&>()(&A::f);
Demo.
I'm using gcc 4.3.2.
I have the following code (simplified):
#include <cstdlib>
template<int SIZE>
class Buffer
{
public:
explicit Buffer(const char *p = NULL) {}
explicit Buffer(const Buffer &other);
const char *c_str() const { return m_buffer; }
private:
char m_buffer[SIZE];
};
typedef Buffer<10> A;
typedef Buffer<20> B;
void Foo(A a) {
}
int main()
{
B b;
Foo(b.c_str()); // line 25 fails compilation
return 1;
}
Compilation yields:
test.cpp: In function ‘int main()’:
test.cpp:25: error: conversion from ‘const char*’ to non-scalar type ‘A’ requested
But there's c-tor receiving const char *.
UDP:
If I remove explicit from 1st c-tor I receive
test.cpp: In function ‘int main()’:
test.cpp:25: error: no matching function for call to ‘Buffer<10>::Buffer(A)’
test.cpp:7: note: candidates are: Buffer<SIZE>::Buffer(const char*) [with int SIZE = 10]
test.cpp:25: error: initializing argument 1 of ‘void Foo(A)’
If I use Foo(A(b.c_str())) I receive:
test.cpp: In function ‘int main()’:
test.cpp:25: error: no matching function for call to ‘Buffer<10>::Buffer(A)’
test.cpp:25: error: initializing argument 1 of ‘void Foo(A)’
Your conversion constructor is declared explicit. Keyword explicit is specifically intended to prevent implicit conversions by that constructor. And an implicit conversion is exactly what you expect to happen in your code (at the Foo call).
Why did you declare your constructor explicit, if you want it to work in implicit conversions?
A and B are totally different types. As Andrey pointed out, there is no implicit callable constructor for conversion. You'll have to write
Foo(A(b.c_str()));
This will create a temporary 'automatic' (unnamed) object of type A using the explicit constructor for const char. And this will be passed to Foo.