Discrepancy with lambda conversion constructor in GCC/MSVC - c++

Which one, if not both, is breaking spec? Tried with MSVC on both MSVC 2013 and MSVC Nov 2013 CTP, GCC was MinGW x64 4.9.1 with -std=c++11.
template<typename ret_type>
class memoizer
{
using func_type = ret_type(*)(const int);
const func_type func;
std::map<int, ret_type> cache;
public:
memoizer(func_type func) : func(func)
{
}
ret_type operator [](const int n)
{
const auto it = cache.find(n);
if(it != cache.end())
return it->second;
return cache[n] = func(n);
}
};
//works in GCC but not MSVC
//error C2065: 'fib' : undeclared identifier
memoizer<int64_t> fib([](const int n)
{
return n < 2 ? n : fib[n - 1] + fib[n - 2];
});
//works in MSVC but not GCC
//error: conversion from '<lambda(int)>' to non-scalar type 'memoizer<long long int>' requested
memoizer<int64_t> fib = [](const int n)
{
return n < 2 ? n : fib[n - 1] + fib[n - 2];
};
This seems to stem from the way they're handling lambda types differently, and when they consider a variable to be defined.

GCC is right.
For your first form:
A variable is considered declared at the end of its declarator, which is before its initialiser. This is why the this form is valid. The famous example is int i = i;, which is syntactically valid and initialises i with its own (indeterminate) value.
For your second form:
Your initialisation with = fails because you have two user-defined conversions. (The lambda type's conversion operator is considered user-defined.) It is analogous to
struct A { };
struct B { B(A) { } };
struct C { C(B) { } };
A a;
C c1(a); // okay
C c2 = a; // error

Related

Inherited std::array and aggregate initialization

I have a need to compare triplets of doubles that were calculated using different processes which causes them to differ by small amounts but should be considered equivalent. One approach that appears to work is to inherit std::array in such a way that the values can be compared within some delta of each other. This appears to work:
template <int precision_equals = 4> // default equal test precision is .1^4 (.0001)
class RGB : public std::array<double,3>
I also need to interop with standard arrays which requires a conversion constructor. However, it appears aggregate initialization is not allowed when a constructor is provided: aggregate initialization.
no user-provided, inherited, or explicit constructors (explicitly defaulted or deleted constructors are allowed)
But I have added this constructor which is needed when assigning from a regular array like b2 = a; in the code:
RGB(const std::array<double,3>& x) {*static_cast<std::array<double,3>*>(this) = x;}
Yet, this seems to work.
RGB<2> b2{{ 1,2,3 }};
Is this not aggregate initialization? Am I missing something?
#include <iostream>
#include <array>
#include <algorithm>
#include <vector>
using std::vector;
using std::array;
using std::cout;
template <int precision_equals = 4> // default equal test precision is .1^4 (.0001)
class RGB : public std::array<double,3>
{
public:
RGB(const std::array<double,3>& x) {*static_cast<std::array<double,3>*>(this) = x;}
friend bool operator==(const RGB& a, const RGB& b)
{
auto resolution = [](int prec)
{
double factor = 1.0;
while (prec--)
factor = factor / 10.0;
return factor;
};
constexpr double delta = resolution(precision_equals);
return a[0] < b[0] + delta && a[0] > b[0] - delta
&& a[1] < b[1] + delta && a[1] > b[1] - delta
&& a[2] < b[2] + delta && a[2] > b[2] - delta;
}
friend bool operator!=(const RGB& a, const RGB& b) { return !(a == b); }
};
int main()
{
// shows vector of inherited arrays can be sorted
vector<RGB<2>> v{ {{1,2.0001,3}}, {{1,2,3}} };
sort(v.begin(), v.end());
array<double, 3> a{ 1,2,3 };
RGB<2> b2{{ 1,2,3 }};
RGB<2> c2{{ 1.001,2,3 }};
RGB<3> b3{{ 1,2,3 }};
RGB<3> c3{{ 1.005,2,3 }};
// comparisons work
cout << "b2==c2: " << (b2 == c2 ? "true\n" : "false\n");
cout << "b3==c3: " << (b3 == c3 ? "true\n" : "false\n");
// assignments to/from regular arrays work
a = b2;
b2 = a;
}
Works in MSVC and GCC. Link to compiler explorer
#LanguageLawyer notes that an assignment conversion operator would remove most of the need for a conversion constructor. Removal of the conversion constructor and replacement by this
RGB& operator=(const std::array<double, 3>& from)
{
//return *this = *static_cast<const RGB*>(&from); // UB
(*this)[0] = from[0]; // ugly version that's not UB
(*this)[1] = from[1];
(*this)[2] = from[2];
return *this;
}
allows the code to compile so my use case is solved. However, the question whether the conversion constructor prohibits aggregate initialization remains.
Calling base constructor should be better
Untested code
RGB(const std::array<double,3>& x) : std::array<double, 3>(x) {}
or a slight rewrite
using BaseRGB = std::array<double,3>;
template <int precision_equals = 4> // default equal test precision is .1^4 (.0001)
class RGB : public BaseRGB {
public:
RGB(const BaseRGB& x) : BaseRGB(x) {}
// or even
using BaseRGB::BaseRGB; // using the constructor directly if you don't set up anything more.

Do compilers avoid intermediate integral promotion or conversions?

Consider a class like:
struct mystruct
{
constexpr operator char() {return x;}
signed char x;
};
and an operation like:
mystruct m;
m.x = /* something at runtime */
int i = 3 * m + 45ULL * m;
Are compilers able to skip the temporary conversion to char and convert directly m to the required type in the 3 * m + 45ULL * m expression?
Seems like GCC version 5.3.0 is able to optimize the call to cast function, while Clang 3.7 is not as smart.
For this piece of code:
struct mystruct
{
constexpr operator char() const {return x;}
signed char x;
} m;
void func(const int num) {
m.x = num*2;
int i = 3 * m + 45ULL * m;
}
you can check compiled assembly and compare them:
Clang with cast vs Clang with direct reference to field
Gcc with cast vs Gcc with direct reference to field
Though in a slightly different situation Clang does manage to optimize the call to cast function.

What is the correct way to initialize a variable in C++

I have the following code :
bool c (a == b);
and
bool c {a == b};
where a and b are some variables of same type.
I want to know that, what is the difference in above two initializations and which one should be preferred in what conditions ? Any kind of help will be appreciated.
Both forms are direct initialization.
Using curly braces {} for initialization checks for narrowing conversions and generates an error if such a conversion happens. Unlike (). (gcc issues a warning by default and needs -Werror=narrowing compiler option to generate an error when narrowing occurs.)
Another use of curly braces {} is for uniform initialization: initialize both types with and without constructors using the same syntax, e.g.:
template<class T, class... Args>
T create(Args&&... args) {
T value{std::forward<Args>(args)...}; // <--- uniform initialization + perfect forwarding
return value;
}
struct X { int a, b; };
struct Y { Y(int, int, int); };
int main() {
auto x = create<X>(1, 2); // POD
auto y = create<Y>(1, 2, 3); // A class with a constructor.
auto z = create<int>(1); // built-in type
}
The only drawback of using curly braces {} for initialization is its interaction with auto keyword. auto deduces {} as std::initializer_list, which is a known issue, see "Auto and braced-init-lists".
First one is the C++03 style direct initialization.
The second is C++11 style direct initialization, it additionally checks for narrowing conversions. Herb Sutter recommends the following in new code:
auto c = <expression>;
or when you want to commit to specific type T:
auto c = T{<expression>};
One known drawback with curly braces when T is some class with overloaded constructor, where one constructor gets std::initializer_list as parameter, std::vector for example:
auto v = std::vector<int>{10}; // create vector<int> with one element = 10
auto v = std::vector<int>(10); // create vector<int> with 10 integer elements
Now we have five forms of initializations. They are
T x = expression;
T x = ( expression );
T x ( expression );
T x = { expression };
T x { expression };
Each of the forms has its own peculirities. :)
For example let's assume that you have the following declarations in the global namespace
int x;
void f( int x ) { ::x = x; }
int g() { return x ; }
long h() { return x; }
then in main you can write
int main()
{
int x ( g() );
}
This code will compile successfully.
However a programmer by mistake made a typo
int main()
{
int x; ( g() );
^^
}
Oops! This code also compiles successfully.:)
But if the programmer would write
int main()
{
int x = ( g() );
}
and then make a typo
int main()
{
int x; = ( g() );
^^
}
then in this case the code will not compile.
Well let's assume that the programmer decided at first to set a new value for the global variable x before initializing the local variable.
So he wrote
int main()
{
int x ( f( 10 ), g() );
}
But this code does not compile!
Let's insert equality sign
int main()
{
int x = ( f( 10 ), g() );
}
Now the code compiles successfully!
And what about braces?
Neither this code
int main()
{
int x { f( 10 ), g() };
}
nor this code
int main()
{
int x = { f( 10 ), g() };
}
compiles!:)
Now the programmer decided to use function h(), He wrote
int main()
{
int x ( h() );
}
and his code compiles successfully. But after a time he decided to use braces
int main()
{
int x { h() };
}
Oops! His compiler issues an error
error: non-constant-expression cannot be narrowed from type 'long' to
'int' in initializer list
The program decided to use type specifier auto. He tried two approaches
int main()
{
auto x { 10 };
x = 20;
}
and
int main()
{
auto x = { 10 };
x = 20;
}
and ...some compilers compiled the first program but did not compile the second program and some compilers did not compile the both programs.:)
And what about using decltype?
For example the programmer wrote
int main()
{
int a[] = { 1, 2 };
decltype( auto ) b = a;
}
And his compiler issued an error!
But when the programmer enclosed a in parentheses like this
int main()
{
int a[] = { 1, 2 };
decltype( auto ) b = ( a );
}
the code compiled successfully!:)
Now the programmer decided to learn OOP. He wrote a simple class
struct Int
{
Int( int x = 0 ) : x( x ) {}
int x;
};
int main()
{
Int x = { 10 };
}
and his code compiles successfully.
But the programmer has known that there is function specifier explicit and he has decided to use it
struct Int
{
explicit Int( int x = 0 ) : x( x ) {}
int x;
};
int main()
{
Int x = { 10 };
}
Oops! His compiler issued an error
error: chosen constructor is explicit in copy-initialization
The programmer decided to remove the assignment sign
struct Int
{
explicit Int( int x = 0 ) : x( x ) {}
int x;
};
int main()
{
Int x { 10 };
}
and his code compiled successfully!:)

Pointer Wrapper: dereference operator

I'm pretty new to C++ and as an exercise (and perhaps eventually .Net utility) I'm doing a pointer wrapper (actually in C++/CLI, but this applies to C++ as well). This pointer wrapper (called Apont) currently behaves just like a pointer would, as the test below can show, if lines marked 1. and 2. are commented out:
int main(array<System::String ^> ^args)
{
double ia = 10; double ip = 10;
double *p = &ip; // pointer analogy
Apont<double> ^a =
gcnew Apont<double>(ia); // equivalent to what's below, without errors
a = ~ia;/* 1. IntelliSense: expression must have integral or unscoped enum type
error C2440: '=' : cannot convert from 'double' to 'Utilidades::ComNativos::Apont<T> ^'
error C2171: '~' : illegal on operands of type 'double'*/
Console::WriteLine("ip = {0}; *p = {1}; ia = {2}; !a = {3}", ip, *p, ia, !a);
ia = 20; ip = 20;
Console::WriteLine("ip = {0}; *p = {1}; ia = {2}; !a = {3}", ip, *p, ia, !a);
*p = 30; // pointer analogy
a->Valor = 30; // does exacly what's below, without errors
!a = 30;/* 2. IntelliSense: expression must be a modifiable lvalue
error C2106: '=' : left operand must be l-value */
Console::WriteLine("ip = {0}; *p = {1}; ia = {2}; !a = {3}", ip, *p, ia, !a);
//a->Dispose();
Console::ReadKey();
p = nullptr;
return 0;
}
There are two things I don't like here, marked with 1. and 2. in the code comments, before the lines with errors. The operator~ (see 1.) is defined outside Apont, below:
template<typename T> static Apont<T>^% operator ~(T& valor)
{
return gcnew Apont<T>(valor);
}
I think this one has to be defined outside Apont, but I'm not sure. I cannot understand very well the errors it produces (these are, of course, in the use, not in the definition).
To set the value to which the instance of Apont refers I must use a property (the line marked 2. doesn't work, with errors in the setting usage only), Apont::Valor, which is the equivalent to use *p. What I'd like to do is as I use *p to get or set the value it points to, use !a with the same effect on Apont. Here's Apont::operator!()'s current definition:
T operator !()
{
return Valor;
}
As you can see in 2. (comment in the code, before the respective errors), it doesn't work for setting a value. Maybe I should return a reference? Make another operator with the same name, perhaps outside the class? I tried several options, however, I got similar errors, and came out more confused.
The question is: how can I make an operator that behaves like & (in this case, ~) and one that behaves like * (in this case, !, for dereference, but that behaves like Apont::Valor, whose old definition you can see below)?
property T Valor
{
T get()
{
if (pointer != nullptr)
return *pointer;
else if (eliminado && ErroSeEliminado) // means "disposed && ErrorIfDisposed"
throw gcnew ObjectDisposedException("O objeto já foi pelo menos parcialmente eliminadao.");
else if (ErroSeNulo) // means "ErrorIfNull"
throw gcnew NullReferenceException();
else
return 0;
// don't worry, this is not default behavior, it is returned only if you want to ignore all errors and if the pointer is null
}
void set(T valor)
{
*pointer = valor;
}
}
Let me recap in a new answer for clarity.
Solving the ! operator is easy, as I said in my previous answer, just add a reference.
So for the operator ~, the goal was to have it behave like the & operator and call the constructor of the pointer wrapper class.
I don't think that is possible. It is certainly possible for user defined objects, but I don't think it is possible to overload unary operators for builtin types. So there are three solutions depending on what you prefer:
The first one does exactly what you want, but will break for primitive types:
#include <iostream>
template<typename T>
struct A {
T* payload;
A()
: payload(NULL){}
A(T *ptr)
: payload(ptr) {}
T& operator !(){
return *payload;
}
};
// this will not work for primary types
template<typename T>
A<T> operator ~(T &b){
return A<T>(&b);
}
struct B{
int test;
};
int main(){
B b; b.test = 4;
A<B> a;
a = ~b; // I think this is what you want
std::cerr << (!a).test << std::endl;
// this does not work
//int i = 4;
//A<int> a;
//a = ~i;
}
Second solution: use a compound assignment operator. Pros are the side effects are minimal, cons is this is not very intuitive and might break the nice design you had in mind.
#include <iostream>
template<typename T>
struct A {
T* payload;
A() : payload(NULL){}
T& operator !(){
return *payload;
}
};
template<typename T>
A<T>& operator &=(A<T> &a, T& b){ // should be friend of the above
a.payload = &b;
return a;
}
int main(){
int i = 3;
A<int> a;
a &= i;
std::cerr << !a << std::endl;
}
Third solution: overload the basic assignment operator. This is more intuitive to write but has a lot of side effects:
#include <iostream>
template<typename T>
struct A {
T* payload;
A() : payload(NULL){}
T& operator !(){
return *payload;
}
A<T>& operator = (T & b) {
payload = &b;
return *this;
}
};
int main(){
int i = 3;
A<int> a;
a = i;
std::cerr << !a << std::endl;
}
Someone might have a solution to hijack the operators for primitive types, but i can't think of any simple solution.
If i understood your code correctly, you want the operator ~ to return a copy of the pointer wrapper and the operator ! to act as dereference?
In this case, you can define the unary operator ~ inside the Apont class which calls a copy constructor. And the operator ! has to return a reference indeed if you want to asign a value.
I think the following c++ code defines what you want to do (I renamed Apont to A):
#include <iostream>
template<typename T>
struct A {
T* payload;
A(T *ptr)
:payload(ptr) {}
A(const A&other)
:payload(other.payload) {}
T& operator !(){
return *payload;
}
T* operator ~(){
return payload;
}
};
int main(){
#define PRINT(X) std::cerr << #X << " = " << X << std::endl
int i = 0;
PRINT(i);
A<int> a(&i);
!a = 1;
PRINT(i);
A<int> b = ~a;
!b = 2;
PRINT(i);
}
The output of the code above is:
i = 0
i = 1
i = 2
According to your comments, you said you wanted the operator ! to behave exactly like the wrapped pointer. You can do so, but then the syntax changes and you need to dereference it to assign a new value (because it is a pointer...). ie something like:
#include <iostream>
template<typename T>
struct A {
T* payload;
A(T *ptr): payload(ptr) {}
// this now behaves like accessing the wrapped pointer directly
T*& operator !(){
return payload;
}
};
int main(){
#define PRINT(X) std::cerr << #X << " = " << X << std::endl
int i = 0;
int j = 999;
PRINT(i);
A<int> a(&i);
*(!a) = 1; // note the change of syntax here
PRINT(*!a); // and here
!a = &j; // but now you can change the wrapped pointer through the operator
PRINT(*!a);
}

which identifiers are available to lambda in constructor initializer list

more to the point, what's wrong with this code:
#include <assert.h>
#include <functional>
using namespace std;
template< class BaseObjectId >
class Check
{
protected:
Check( function<bool()> const f ) { assert( f() ); }
};
template< int tpMinValue, int tpMaxValue >
class IntegerSubrange
: private Check< IntegerSubrange< tpMinValue, tpMaxValue > >
{
private:
int value_;
public:
enum :int { minValue = tpMinValue, maxValue = tpMaxValue };
static bool rangeContains( int const x )
{
return (minValue <= x && x <= maxValue);
}
operator int() const
{
return value_;
}
void operator/=( int const rhs )
{
value_ /= rhs;
assert( rangeContains( value_ ) );
}
explicit IntegerSubrange( int const value )
: Check< IntegerSubrange< tpMinValue, tpMaxValue > >(
[=]() -> bool { return rangeContains( value ); }
)
, value_( value )
{}
};
int main() {}
Visual C++ reports a syntax error:
foo.cpp
foo.cpp(41) : error C2059: syntax error : ')'
foo.cpp(44) : see reference to class template instantiation 'IntegerSubrange' being compiled
foo.cpp(42) : error C2059: syntax error : ','
foo.cpp(43) : error C2334: unexpected token(s) preceding '{'; skipping apparent function body
To summarize the comments: The questioner's code is valid. Apparently some compilers older than GCC 4.4 or Visual C++ 2011 will reject it, due to those compilers' incomplete support for C++11-style lambdas. But modern compilers (and certainly any compiler that claims to support the new C++11 standard) should handle it just fine.
To answer your question literally: In a ctor-initializer-list, the same identifiers are available (and refer to the same things) as they would refer to if you moved them inside the curly braces of the constructor function itself. In particular, this means that you can do
class C {
const char *p_ = "foo";
char c_;
C(int): p_(__func__) { } // referring to "__func__"
C(double): c_(*this->p_) { } // referring to "this"
};
Here's what the Standard has to say on the subject:
Names in the expression-list or braced-init-list of a mem-initializer
are evaluated in the scope of the constructor for which the
mem-initializer is specified. ... [Note: Because the mem-initializer
are [sic] evaluated in the scope of the constructor, the this pointer can be
used in the expression-list of a mem-initializer to refer to the
object being initialized. —end note] (N3337 §12.6.2 #12)