Env: win7, visual 2013 x64
Given a std::chrono::system_clock::time_point tp , and a std::chrono::system_clock::duration dur , how to find the next std::chrono::system_clock::time_point tp2 following :
tp2 = tp - tp % dur + dur
This represents the next time point considering a clock and a heartbeat, for example dur=10s.
I tryied a lot ... my best I guess was this:
using namespace std; // for better readability
template < class duration_t >
system_clock::time_point next_time_aligned_on(const system_clock::time_point & tp, const duration_t & step)
{
const system_clock::duration d = tp.time_since_epoch();
const auto step2 = duration_cast<system_clock::duration>(step);
const auto elapsed_since_last = d % step2;
return tp - elapsed_since_last + step;
}
I got always the same compilation error:
1>C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC
\include\type_traits(1446): error C2446: ':' : no conversion from
'std::chrono::duration<std::chrono::system_clock::rep,std::chrono::system_clock::period>'
to 'std::chrono::system_clock::rep'
1> No user-defined-conversion operator available that can perform
this conversion, or the operator cannot be called
1> C:\trading\tepp\src\tepp/tools/strings.h(49) : see reference
to class template instantiation std::common_type<std::chrono::system_clock::rep,std::chrono::duration<std::chrono::system_clock::rep,std::chrono::system_clock::period>>'
being compiled
1> st_gammalong.cpp(30) : see reference to function template
instantiation 'std::chrono::system_clock::time_point
tepp::next_time_aligned_on<std::chrono::seconds>(const std::chrono::system_clock::time_point &,const duration_t &)'
being compiled
1> with
1> [
1> duration_t=std::chrono::seconds
1> ]
My question: how to use modulo operator in c++11 std::chrono ?
Related
I'm trying to use boost::any_range (with random access tag) in some legacy code, but found that it does not like lambdas. Compilation error seems to complain about the lack of default constructor for lambda objects. Is this expected behavior? Is it by design? I'm on MSVC C++17 with boost version 1.66.
Documentation mentions that transformed_range has the same category as input range:
https://www.boost.org/doc/libs/1_66_0/libs/range/doc/html/range/reference/adaptors/reference/transformed.html
The problem is obviously in somewhere in boost::any_range, because if I just use auto, it works (cf rngneg_auto below)
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/any_range.hpp>
#include <iostream>
#include <vector>
using boost::adaptors::transformed;
using double_range = boost::any_range<const double
, boost::random_access_traversal_tag
, const double>;
struct negate
{
constexpr double operator() (const double x) const
{
return -x;
}
};
int main(int argc, char** argv)
{
const std::vector<double> v{ 1.0, 2.0, 3.0 };
// this works
const auto rngneg_auto = v | transformed([](double x) { return -x; });
std::cout << "Second element is " << rngneg_auto[1] << std::endl;
// ... and this
const double_range rngneg = v | transformed(negate());
std::cout << "Second element is " << rngneg[1] << std::endl;
#if 0
// but not that
const double_range rngneg_lambda = v | transformed([](double x) { return -x; });
std::cout << "Second element is " << rngneg_lambda[1] << std::endl;
#endif
return 0;
}
For the first two cases, the program prints
Second element is -2
Second element is -2
Third is a compilation error (I think it's because lambdas aren't default-constructible):
1>\boost.org\boost\1.66.0\include\boost\optional\optional.hpp(733): error C2280: 'main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65> &main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>::operator =(const main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65> &)': attempting to reference a deleted function
1> ***: note: see declaration of 'main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>::operator ='
1>\boost.org\boost\1.66.0\include\boost\optional\optional.hpp(733): note: while compiling class template member function 'void boost::optional_detail::optional_base<T>::assign_value(main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65> &&)'
1> with
1> [
1> T=main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>
1> ]
1>\boost.org\boost\1.66.0\include\boost\optional\optional.hpp(262): note: see reference to function template instantiation 'void boost::optional_detail::optional_base<T>::assign_value(main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65> &&)' being compiled
1> with
1> [
1> T=main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>
1> ]
1>\boost.org\boost\1.66.0\include\boost\optional\optional.hpp(831): note: see reference to class template instantiation 'boost::optional_detail::optional_base<T>' being compiled
1> with
1> [
1> T=main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>
1> ]
1>\boost.org\boost\1.66.0\include\boost\range\detail\default_constructible_unary_fn.hpp(48): note: see reference to class template instantiation 'boost::optional<F>' being compiled
1> with
1> [
1> F=main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>
1> ]
1>\boost.org\boost\1.66.0\include\boost\utility\detail\result_of_iterate.hpp(70): note: see reference to class template instantiation 'boost::range_detail::default_constructible_unary_fn_wrapper<F,R>' being compiled
1> with
1> [
1> F=main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,
1> R=double
1> ]
1>\boost.org\boost\1.66.0\include\boost\utility\detail\result_of_iterate.hpp(43): note: see reference to class template instantiation 'boost::detail::cpp0x_result_of<F (T0)>' being compiled
1> with
1> [
1> F=const boost::range_detail::default_constructible_unary_fn_wrapper<main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,double> &,
1> T0=const double &
1> ]
1>\boost.org\boost\1.66.0\include\boost\mpl\eval_if.hpp(41): note: see reference to class template instantiation 'boost::result_of<const UnaryFunc &(const double &)>' being compiled
1> with
1> [
1> UnaryFunc=boost::range_detail::default_constructible_unary_fn_wrapper<main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,double>
1> ]
1>\boost.org\boost\1.66.0\include\boost\iterator\iterator_adaptor.hpp(154): note: see reference to class template instantiation 'boost::mpl::eval_if<boost::is_same<T,boost::iterators::use_default>,DefaultNullaryFn,boost::mpl::identity<T>>' being compiled
1> with
1> [
1> T=boost::iterators::use_default,
1> DefaultNullaryFn=boost::result_of<const boost::range_detail::default_constructible_unary_fn_wrapper<main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,double> &(const double &)>
1> ]
1>\boost.org\boost\1.66.0\include\boost\iterator\transform_iterator.hpp(55): note: see reference to class template instantiation 'boost::iterators::detail::ia_dflt_help<Reference,boost::result_of<const UnaryFunc &(const double &)>>' being compiled
1> with
1> [
1> Reference=boost::iterators::use_default,
1> UnaryFunc=boost::range_detail::default_constructible_unary_fn_wrapper<main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,double>
1> ]
1>\boost.org\boost\1.66.0\include\boost\iterator\transform_iterator.hpp(81): note: see reference to class template instantiation 'boost::iterators::detail::transform_iterator_base<UnaryFunc,Iterator,Reference,Value>' being compiled
1> with
1> [
1> UnaryFunc=boost::range_detail::default_constructible_unary_fn_wrapper<main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,double>,
1> Iterator=std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<double>>>,
1> Reference=boost::iterators::use_default,
1> Value=boost::iterators::use_default
1> ]
1>c:\program files (x86)\microsoft visual studio\2017\professional\vc\tools\msvc\14.14.26428\include\xutility(652): note: see reference to class template instantiation 'boost::iterators::transform_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<F,R>,It,boost::iterators::use_default,boost::iterators::use_default>' being compiled
1> with
1> [
1> F=main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,
1> R=double,
1> It=std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<double>>>
1> ]
1>\boost.org\boost\1.66.0\include\boost\iterator\iterator_categories.hpp(120): note: see reference to class template instantiation 'std::iterator_traits<Iterator>' being compiled
1> with
1> [
1> Iterator=boost::iterators::transform_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,double>,std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<double>>>,boost::iterators::use_default,boost::iterators::use_default>
1> ]
1>\boost.org\boost\1.66.0\include\boost\range\iterator_range_core.hpp(156): note: see reference to class template instantiation 'boost::iterators::iterator_traversal<IteratorT>' being compiled
1> with
1> [
1> IteratorT=boost::iterators::transform_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,double>,std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<double>>>,boost::iterators::use_default,boost::iterators::use_default>
1> ]
1>\boost.org\boost\1.66.0\include\boost\range\iterator_range_core.hpp(436): note: see reference to class template instantiation 'boost::iterator_range_detail::pure_iterator_traversal<IteratorT>' being compiled
1> with
1> [
1> IteratorT=boost::iterators::transform_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,double>,std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<double>>>,boost::iterators::use_default,boost::iterators::use_default>
1> ]
1>\boost.org\boost\1.66.0\include\boost\range\adaptor\transformed.hpp(44): note: see reference to class template instantiation 'boost::iterator_range<boost::iterators::transform_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<F,R>,It,boost::iterators::use_default,boost::iterators::use_default>>' being compiled
1> with
1> [
1> F=main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,
1> R=double,
1> It=std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<double>>>
1> ]
1>***: note: see reference to class template instantiation 'boost::range_detail::transformed_range<main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,const std::vector<double,std::allocator<_Ty>>>' being compiled
1> with
1> [
1> _Ty=double
1> ]
1>***: note: 'main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65> &main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>::operator =(const main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65> &)': function was explicitly deleted
It's choking because it's trying to figure out how to construct the any_range from the transformed_range and thinks the lambda is a default constructible type. I haven't looked deeply into why but I imagine this is because there's nothing explicitly saying that it isn't and the lambda's type is unique. Of course it's meaningless to try to default construct the lambda's type.
I'd say the simplest way to make it work is to use a type where it's clear (through standard templates) that it can't be default constructed, ie std::function<>. This compiles:
const double_range rngneg_lambda = v | transformed(static_cast<std::function<double(double)>>([](double x) { return -x; }));
I encounter a strange question about rxcpp.
When capturing a rxcpp::connectable_observable variable and call it's connect method, I got a compile error as follow.
1>------ Build started: Project: LearnRx, Configuration: Debug x64 ------
1>Main.cpp
1>c:\users\liuzichao\source\repos\learnrx\learnrx\main.cpp(19): warning C4477: 'printf' : format string '%d' requires an argument of type 'int', but variadic argument 1 has type 'std::thread::id'
1>c:\users\liuzichao\source\repos\learnrx\learnrx\main.cpp(259): error C2662: 'rxcpp::composite_subscription rxcpp::connectable_observable<SourceValue,Multicast>::connect(rxcpp::composite_subscription)': cannot convert 'this' pointer from 'const Result' to 'rxcpp::connectable_observable<SourceValue,Multicast> &'
1> with
1> [
1> SourceValue=int,
1> Multicast=rxcpp::operators::detail::multicast<int,rxcpp::observable<int,rxcpp::sources::detail::create<int,publish_example::<lambda_3a462b77ca22ce68ef79403bfe94c65d>>>,rxcpp::subjects::subject<int>>
1> ]
1> and
1> [
1> Result=rxcpp::connectable_observable<int,rxcpp::operators::detail::multicast<int,rxcpp::observable<int,rxcpp::sources::detail::create<int,publish_example::<lambda_3a462b77ca22ce68ef79403bfe94c65d>>>,rxcpp::subjects::subject<int>>>
1> ]
1> and
1> [
1> SourceValue=int,
1> Multicast=rxcpp::operators::detail::multicast<int,rxcpp::observable<int,rxcpp::sources::detail::create<int,publish_example::<lambda_3a462b77ca22ce68ef79403bfe94c65d>>>,rxcpp::subjects::subject<int>>
1> ]
1>c:\users\liuzichao\source\repos\learnrx\learnrx\main.cpp(259): note: Conversion loses qualifiers
1>c:\users\liuzichao\source\repos\learnrx\learnrx\main.cpp(334): warning C4477: 'printf' : format string '%d' requires an argument of type 'int', but variadic argument 1 has type 'std::thread::id'
1>c:\users\liuzichao\source\repos\learnrx\learnrx\main.cpp(338): warning C4477: 'printf' : format string '%d' requires an argument of type 'int', but variadic argument 1 has type 'std::thread::id'
1>c:\users\liuzichao\source\repos\learnrx\learnrx\main.cpp(345): warning C4477: 'printf' : format string '%d' requires an argument of type 'int', but variadic argument 1 has type 'std::thread::id'
1>c:\users\liuzichao\source\repos\learnrx\learnrx\main.cpp(346): warning C4477: 'printf' : format string '%d' requires an argument of type 'int', but variadic argument 1 has type 'std::thread::id'
1>c:\users\liuzichao\source\repos\learnrx\learnrx\main.cpp(348): warning C4477: 'printf' : format string '%d' requires an argument of type 'int', but variadic argument 1 has type 'std::thread::id'
1>Done building project "LearnRx.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
The problem code is shown below.
void publish_example() {
auto o = rxcpp::observable<>::create<int>([](rxcpp::subscriber<int> s) {
s.on_next(0);
s.on_next(1);
}).publish();
o.subscribe([](int v) {printf("%d", v); });
rxcpp::observable<>::timer(std::chrono::microseconds(2000)).subscribe(
[](const int i) {},
[](const std::exception_ptr& e) {},
[o]() {
o.connect();
}
);
}
I tried 2 methods to pass compiling
1. Comment "o.connect()"
1. turn variable o to static variable, so o doesn't need to be captured. code is shown follow
void publish_example() {
static auto o = rxcpp::observable<>::create<int>([](rxcpp::subscriber<int> s) {
s.on_next(0);
s.on_next(1);
}).publish();
o.subscribe([](int v) {printf("%d", v); });
rxcpp::observable<>::timer(std::chrono::microseconds(2000)).subscribe(
[](const int i) {},
[](const std::exception_ptr& e) {},
[]() {
o.connect();
}
);
}
Could you help telling me why the compile error appeared and hwo to figure it?
Thank you!
I figured this out.
What happend in here is because connectable_observable::connect is not a const method. After change it to a const method, the compile error disappeared.
I want to store three arbitrary ints inside a std::vector without defining a struct/class. So I went for std::tuple<>:
std::vector<std::tuple<unsigned int, unsigned int, unsigned int>
Using MS VS 2013, it leads to the following error:
>c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector(1628): error C2036: 'std::tuple<unsigned int,unsigned int,unsigned int> *' : unknown size
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector(1622) : while compiling class template member function 'void std::vector<std::tuple<unsigned int,unsigned int,unsigned int>,std::allocator<_Ty>>::_Tidy(void)'
1> with
1> [
1> _Ty=std::tuple<unsigned int,unsigned int,unsigned int>
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector(945) : see reference to function template instantiation 'void std::vector<std::tuple<unsigned int,unsigned int,unsigned int>,std::allocator<_Ty>>::_Tidy(void)' being compiled
1> with
1> [
1> _Ty=std::tuple<unsigned int,unsigned int,unsigned int>
1> ]
1> d:\projects\gl33\src\nvf.cpp(39) : see reference to class template instantiation 'std::vector<std::tuple<unsigned int,unsigned int,unsigned int>,std::allocator<_Ty>>' being compiled
1> with
1> [
1> _Ty=std::tuple<unsigned int,unsigned int,unsigned int>
1> ]
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped =======
Is this due to limitations in the MSVS2013 compiler? Or am I doing something wrong?
A class type is known (its name is known) but its size is unknown if the type has only been forward-declared, but not defined. E.g.
struct X;
sizeof(X) // error: X is incomplete
The size of a type is important for pointer arithmetic, which is another hint when looking at the compiler error (which mentions a pointer to tuple).
MSDN provides the following example for C2036:
struct A* pA;
int main() {
pA++; // C2036, size of A not known
((char*&)pA)++; // OK, if sizeof(A) == sizeof(char)
}
Where the struct A* pa implicitly forward-declares struct A.
Such a situation can happen with headers of the Standard Library when you don't include all required headers yourself. There are interdependencies between the types in the Standard Library. If a Standard Library header requires only a forward-declaration of tuple, it won't include the heavyweight tuple header itself in an effort to reduce compilation times.
I could reproduce the issue in the OP by including only <vector> but not <tuple>. Solution: manually include all headers you need types from - when using vector<tuple<..>>, include <tuple> (as well as <vector>). In general, including a header guarantees the availability of a certain set of types. To maximize portability, always make sure the headers you've included guarantee that you can use all the types in your program(*).
(*) More specifically, you should make sure that you have a definition for all types your program needs a definition for. Standard Library containers require their value types to be complete (at least at the point where the class template is instantiated). Hence, if your program requires a definition of vector<tuple<unsigned, unsigned>>, it also requires a definition of tuple<unsigned, unsigned>.
I've run into a problem driving me mad. I've implemented a timer using the followin timer entry construct:
typedef std::multimap<boost::posix_time::ptime, events::ITimeout*> TEntryMap;
TEntryMap entries_;
and I insert elements into the multimap with:
boost::posix_time::ptime tTimeout = boost::posix_time::microsec_clock::local_time() + boost::posix_time::milliseconds(timeout);
entries_.insert(std::make_pair(tTimeout, ptr)); // ptr is the events::ITimeout object
and in one translation unit (cpp file) it works perfectly. However, now I need to move this functionality to another cpp file, and now I get a compilation error:
1>Build started 2013-02-07 15:38:18.
1>ClCompile:
1> EventDispatcher.cpp
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(260): error C2678: binary '=' : no operator found which takes a left-hand operand of type 'const boost::posix_time::ptime' (or there is no acceptable conversion)
1> ....\boost\boost\date_time\posix_time\ptime.hpp(57): could be 'boost::posix_time::ptime &boost::posix_time::ptime::operator =(const boost::posix_time::ptime &)'
1> while trying to match the argument list '(const boost::posix_time::ptime, const boost::posix_time::ptime)'
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(259) : while compiling class template member function 'std::pair<_Ty1,_Ty2> &std::pair<_Ty1,_Ty2>::operator =(std::pair<_Ty1,_Ty2> &&)'
1> with
1> [
1> _Ty1=const boost::posix_time::ptime,
1> _Ty2=events::ITimeout *
1> ]
1> ....\eventdispatcher.cpp(72) : see reference to class template instantiation 'std::pair<_Ty1,_Ty2>' being compiled
1> with
1> [
1> _Ty1=const boost::posix_time::ptime,
1> _Ty2=events::ITimeout *
1> ]
1>
I'm clueless and been struggling with this for 2 hours. I see no difference between the working implementation, and the non-working one. The same construct, same multimap, same includes, same everything! ;(
I found the cause of the problem, and it smells like a VS2010 C++ compiler bug (when using std::remove_if). In a function implementation later on in the class using the construct, I tried to remove elements in the map with:
void removeEntry(events::ITimeout* p)
{
std::remove_if(entries_.begin(), entries_.end(),
[&](TEntryMap::value_type& entry)->bool
{
return (entry.second == p);
}
);
}
Changing that code to:
void removeEntry(events::ITimeout* p)
{
TEntryMap::iterator it = std::find_if(entries_.begin(), entries_.end(),
[&](TEntryMap::value_type& entry)->bool
{
return (entry.second == p);
}
);
if (it != entries_.end()) entries_.erase(it);
}
makes the insertion code work. Go figure. Note that even if I use a struct based predicate instead of a lambda closure, it still doesn't work with std::remove_if...
This compiles fine in GCC 3 and 4. MSVC++ can't figure out the type of noFunction and throws some hideous errors. Note if you cast noFunction to BFunction, it works just fine in VS2010.
My question: is this a defect in VS2010, or GCC bending the rules?
#include <map>
using namespace std;
typedef bool (*AFunction)(int arg1, int arg2);
typedef bool (*BFunction)(long arg1, bool arg2);
bool noFunction(long, bool) { return true; }
void test(AFunction a)
{
make_pair(a, noFunction); //fails in VS2010
}
N.B. casting noFunction to BFunction fixes the problem in VS2010.
make_pair(a, (BFunction)noFunction); //works everywhere
.
.
.
Here is the error for reference:
1> makepairtest.cpp
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\type_traits(197): error C2752: 'std::tr1::_Remove_reference<_Ty>' : more than one partial specialization matches the template argument list
1> with
1> [
1> _Ty=bool (__cdecl &)(long,bool)
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtr1common(356): could be 'std::tr1::_Remove_reference<_Ty&&>'
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtr1common(350): or 'std::tr1::_Remove_reference<_Ty&>'
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\type_traits(962) : see reference to class template instantiation 'std::tr1::remove_reference<_Ty>' being compiled
1> with
1> [
1> _Ty=bool (__cdecl &)(long,bool)
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(26) : see reference to class template instantiation 'std::tr1::decay<_Ty>' being compiled
1> with
1> [
1> _Ty=bool (__cdecl &)(long,bool)
1> ]
1> c:\xxx\makepairtest.cpp(14) : see reference to class template instantiation 'std::tr1::_Unrefwrap<_Type>' being compiled
1> with
1> [
1> _Type=bool (__cdecl &)(long,bool)
1> ]
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\type_traits(965): error C2528: 'abstract declarator' : pointer to reference is illegal
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\type_traits(349): error C2528: 'type' : pointer to reference is illegal
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\type_traits(967) : see reference to class template instantiation 'std::tr1::add_pointer<_Ty>' being compiled
1> with
1> [
1> _Ty=bool (__cdecl &)(long,bool)
1> ]
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(148): error C2535: 'std::_Pair_base<_Ty1,_Ty2>::_Pair_base(const _Ty1 &,const _Ty2)' : member function already defined or declared
1> with
1> [
1> _Ty1=bool (__cdecl *)(int,int),
1> _Ty2=bool (__cdecl &)(long,bool)
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(134) : see declaration of 'std::_Pair_base<_Ty1,_Ty2>::_Pair_base'
1> with
1> [
1> _Ty1=bool (__cdecl *)(int,int),
1> _Ty2=bool (__cdecl &)(long,bool)
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(174) : see reference to class template instantiation 'std::_Pair_base<_Ty1,_Ty2>' being compiled
1> with
1> [
1> _Ty1=bool (__cdecl *)(int,int),
1> _Ty2=bool (__cdecl &)(long,bool)
1> ]
1> c:\xxx\makepairtest.cpp(14) : see reference to class template instantiation 'std::pair<_Ty1,_Ty2>' being compiled
1> with
1> [
1> _Ty1=bool (__cdecl *)(int,int),
1> _Ty2=bool (__cdecl &)(long,bool)
1> ]
Taking the address of noFunction works with VC10 and gcc 4.5.2, i.e.:
make_pair(a, &noFunction);
Per the error message you posted, I would guess it has to do with how VC handles binding to rvalues.
"My question: is this a defect in VS2010, or GCC bending the rules?"
When in doubt blame Visual C++ and/or Bill Gates. Note that there is a difference between the value of noFunction when used in your code and the type defined by BFunction. noFunction will be a reference to a function whereas BFunction defines a pointer to a function. It is a bit hard to explain but it might help to contemplate the following program.
#include <iostream>
#include <typeinfo>
bool noFunction(long, bool) { return true; }
typedef bool (function_ref)(long, bool);
typedef bool (*function_ptr)(long, bool);
int
main()
{
std::cout << typeid(noFunction).name() << '\n';
std::cout << typeid(&noFunction).name() << '\n';
std::cout << typeid(function_ref).name() << '\n';
std::cout << typeid(function_ptr).name() << '\n';
return 0;
}
It seems that Visual C++ is choking on function references. I'm not sure if there is a legitimate reason why it would reject that but I would expect that you should be able to construct a pair with types that are a model of copy constructable. Eg you should be able construct but not assign std::pair<int, int const&>.