I am doing a project for my class where the instructor had given us some code snippets and we were asked to modify it. The code compiles correctly in my class computer in Visual Studio but when I try to compile it with gcc it gives me an error.
The error I am getting is:
||=== Build: Debug in Project (compiler: GNU GCC Compiler) ===|
/home/nitin/Read.h|45|error: declaration of ‘std::vector<rv> rvs::rv’ [-fpermissive]|
/home/nitin/Read.h|35|error: changes meaning of ‘rv’ from ‘struct rv’ [-fpermissive]|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
The code from the error is snippet for this is:
struct rv
{
double val, prob;
rv(const double v, const double p): val(v), prob(p) {};
};
struct rvs
{
int row_n, col_n;
vector<rv> rv;
rvs(const int r=-2, const int c=-2): row_n(r), col_n(c) {};
};
Could you please let me know what the problem could be?
Your declarations violate the following rule
3.3.7 Class scope [basic.scope.class]
1 The following rules describe the scope of names declared in classes.
...
2) A name N used in a
class S shall refer to the same declaration in its context and when
re-evaluated in the completed scope of S. No diagnostic is required
for a violation of this rule.
At the point of vector declaration name rv refers to a type struct rv. But when reevaluated in the scope of complete class rvs it, refers to class member rvs::rv. Such inconsistency is an error in C++.
A similar error is illustrated by an example in the standard
enum { i = 1 };
class X {
char v[i]; // error: i refers to ::i
// but when reevaluated is X::i
...
enum { i = 2 };
};
As #Ben Voigt stated in the comment, if you explicitly resolve the conflict between rv as struct rv and rv as rvs::rv, the error will go away. You can do it by either using elaborate type specifier struct rv or by specifying scope explicitly ::rv.
Note that this is one of those errors which are not guaranteed/required to be caught by the compiler.
You have a type called rv and a member variable called rv. How is the compiler supposed to know which one you mean when you write rv?
Strictly this is invalid code, but Visual Studio seems to be willing to try to let you shoot yourself in the foot.
Related
I found this situation in my recent project. I wanna ask if it is designed as so, what's the underlying mechanism, and how is it useful?
Although I know the subscript in parameters list is somehow useless to compiler, but in my situation, it might be better to raise an error and stop compile.
The source code:
#include <cstdio>
template<typename Type>
class A{
public:
// passes compile, although it is not declared
void print(int data[Type::len]) { // Line 7
printf("%d\n", data[0]);
}
// error: not declared
// void print(int data[dummy]) {
// printf("%d\n", data[0]);
// }
};
// error: not declared
// void print(int data[A<double>::len]) {
// printf("%d\n", data[0]);
// }
int main() {
A<int> a;
int x[12] = { 0 };
a.print(x); // Line 23
return 0;
}
Compile command using gcc 11.3.0:
g++ -o a a.cpp -Wall -Wextra
No compile output, program prints a "0" and exits with 0.
But in msvc 19.33.31630, it raises C2825, C2510 on line 7, and C2670 on line 23.
There should be an error and that there isn't one is a known bug in GCC.
If the array bound Type::len was valid, then the type int[Type::len] in the function parameter would be rewritten to int* in the instantiation, as is always the case for array types in function parameters. So the actual value of the array bound will not matter from there on out.
However, if Type::len is not a valid constant expression with a suitable value for an array bound, then substitution should fail and the program should be ill-formed. In case of T=int, Type::len is not a valid expression at all and so it should fail to compile (or at least issue some diagnostic). This should happen already at A<int> a; (which causes implicit instantiation of A<int> including A<int>::print's declaration), even if no actual call to print is present.
It seems GCC is performing the rewriting step too early without verifying that the expression in the array bound is actually valid in the substitution.
GCC has a meta-bug report with multiple linked individual bug reports related to this here.
I am trying to use the automatic differentiation library Adept and I made it work with gcc 4.9.0 and icc 16.0.2 but failed with VS 2017 and Clang 4.0.1
I have reduced the problem to the following snippet and, while I am addressing the issue with the library creators, for the sake of the knowledge I would like to know why this piece of code works in the two mentioned compilers and fails to build in the other two.
template <typename A>
struct Expression
{
static const int rank = A::rank_;
};
struct EndIndex : public Expression<EndIndex>
{
static const int rank_ = 0;
};
int main(int argc, char ** argv)
{
return 0;
}
Output for VS 2017 is:
1>------ Build started: Project: Test, Configuration: Debug Win32 ------
1>Source.cpp
1>d:\Test\source.cpp(4): error C2039: 'rank_': is not a member of 'EndIndex'
1>d:\Test\source.cpp(7): note: see declaration of 'EndIndex'
1>d:\Test\source.cpp(8): note: see reference to class template instantiation 'Expression<EndIndex>' being compiled
1>d:\Test\source.cpp(4): error C2065: 'rank_': undeclared identifier
1>d:\Test\source.cpp(4): error C2131: expression did not evaluate to a constant
1>d:\Test\source.cpp(4): note: failure was caused by non-constant arguments or reference to a non-constant symbol
1>d:\Test\source.cpp(4): note: see usage of 'rank_'
1>Done building project "Test.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
And output for Clang 4.0.1:
source.cpp:4:37: error: no member named 'rank_' in 'EndIndex'
static const int rank = A::rank_;
~~~^
source.cpp:7:38: note: in instantiation of template class 'Expression<EndIndex>' requested here
struct EndIndex : public Expression<EndIndex>
It probably happens because rank_ is not defined at that stage.
The following fixes it for Apple LLVM version 9.0.0 (clang-900.0.38):
template <typename A>
struct Expression
{
static const int rank;
};
struct EndIndex : public Expression<EndIndex>
{
static const int rank_ = 0;
};
template <typename A>
const int Expression<A>::rank = A::rank_;
Visual C++ and clang are simply unable to find rank_ member of EndIndex because it's being accessed before declared. Such fancy code often leads to problems in some environments.
I am using Orwell Dev C++ IDE. Recently I tested following simple program in which I forgot to put semicolon (;) but still it compiles fine in C but not in C++. Why? What is the reason?
// C program compiles & runs fine, even ; missing at end of struct
#include <stdio.h>
struct test
{ int a,b}; // missing semicolon
int main()
{
struct test d={3,6};
printf("%d",d.a);
return 0;
}
[Warning] no semicolon at end of struct or union [enabled by default]
// Following is compilation error in C++
#include <stdio.h>
struct test
{ int a,b}; // missing semicolon
int main()
{
struct test d={3,6};
printf("%d",d.a);
return 0;
}
[Error] expected ';' at end of member declaration
I also tried same C program in codeblocks 13.12 IDE but it shows following error message
error: no semicolon at end of struct or union.
Why different error messages given by different implementations?
The semicolon is required by both languages. Specifically, C specifies the declaration of one or more structure members as
struct-declaration:
specifier-qualifier-list struct-declarator-list ;
and C++ specifies the declaration of one or more class member variables as
member-declaration:
attribute-specifier-seq<opt> decl-specifier-seq<opt> member-declarator-list<opt> ;
both of which require a semicolon at the end.
You'll have to ask the compiler writers why their C++ compiler is more strict than their C compiler. Note that the language specifications only require a "diagnostic" if a program is ill-formed, so it's legitimate either to issue a warning and continue compiling as if the semicolon were present, or to issue an error and stop.
It looks like your IDE is using GCC as its compiler; in which case you could use -Werror to convert warnings into errors, if you'd prefer stricter diagnostics.
I have a problem compiling a c++ program with gcc version 4.6.3; I can compile this program with microsoft compiler (v 9.0) without problems.
This program is using some of my libraries I always used with microsoft compiler.
problem is when I try to pass a reference as argument that is a subtype of another: pseudo example here:
class ObjManager{..}
class SubObjMng : public ObjManager{
public:
inline SubObjMng() : ObjManager(0, ... ){}
};
class Test{
public:
Test(int i, ObjManager &obj_mng);
}
int main(){
SubObjMng myobjmng;
Test t(0, myobjmng); //GCC ERROR HERE
}
output of the error is (real output for my program):
globals.h:227:40: error: no matching function for call to cdk::HashMap::HashMap(unsigned int, cdk::PtrObjMng, cdk::cstrObjMng)
globals.h:227:40: note: candidates are:
contrib/cdklib/cdk_struct.h:485:12: note: cdk::HashMap::HashMap(uint32_t, cdk::ObjManager&, cdk::ObjManager&)
contrib/cdklib/cdk_struct.h:485:12: note: no known conversion for argument 2 from cdk::PtrObjMng to cdk::ObjManager&
anyone can help?
thanks!
cdk::PtrObjMng should inherit from cdk::ObjMng, making polymorphism possible through references. Otherwise this is a no-go according to what the compiler says.
Of course this might not be the root of your problem, I wish we could see the implementation of your constructor.
I am trying create a typedef for a template that needs a pointer to member, from within a class. The best way to describe it is to show the minimal sample code:
template<typename T, int T::*MV>
struct Bar
{
const int &value(const T &t) const
{
return (t.*MV);
}
};
struct Foo
{
int baz;
typedef Bar<Foo, &Foo::baz> GetBaz; // Compiler error
};
typedef Bar<Foo, &Foo::baz> GetFooBaz; // Compiles just fine
int main(int argc, char* argv[])
{
Foo f = { 42 };
Foo::GetBaz b; // Fails to compile
GetFooBaz b2; // Fine
int val = b.value(f); // Fails to compile because of above
int val2 = b2.value(f); // Fine
}
I am not necessarily dead-set on getting access to a member pointer in this way, I would be fine just knowing the offset to the variable and having the Bar::value function perform trickery.
As a last resort, I suppose I could use a traits class since the would move the definition outside of the class, but I would prefer to be able to declare the typedef near the variable being used.
And, to answer the "why would you want to do that" question, this is all for an IoC container that closely represents the way MEF (C# works).
The specific compiler I am using is VC12, but it would be nice if VC11 supported it as well.
Thanks
EDIT:
Here are the error messages
1>------ Build started: Project: MemVarBug, Configuration: Debug Win32 ------
1> MemVarBug.cpp
1>memvarbug.cpp(20): error C2327: 'Foo::baz' : is not a type name, static, or enumerator
1>memvarbug.cpp(20): error C2065: 'baz' : undeclared identifier
1>memvarbug.cpp(20): error C2975: 'MV' : invalid template argument for 'Bar', expected compile-time constant expression
1> memvarbug.cpp(7) : see declaration of 'MV'
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
you can do the following trick:
declare baz to be int[1];
array of size one, in this case calling baz will return the pointer and calling *baz will return the value.