I’m trying to puzzle out how clang determines what C++ template static member variables require instantiation, and I’m seeing some behavior that has me confused.
Given the following code:
#include <stdio.h>
#include <typeinfo>
int report(const char *name)
{
printf("Reporting class: %s\n", name);
return 0;
}
template<typename ReportedClass>
class reported_class
{
public:
reported_class()
{
_reported_instances++;
}
private:
static int _reported_instances;
};
template<typename ReportedClass>
int reported_class<ReportedClass>::_reported_instances = report(typeid(ReportedClass).name());
class foo : reported_class<foo>
{
public:
int baz() { return 0; }
};
class bar : reported_class<bar>
{
public:
bar() { }
int baz() { return 0; }
};
int main(int argc, char **argv)
{
return 0;
}
When I run it, I see the following:
$ c++ -v
Apple LLVM version 5.0 (clang-500.0.68) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.1.0
Thread model: posix
$ c++ test.cpp
$ ./a.out
Reporting class: 3bar
$
Why is the static for reported_class being instantiated, but not the one for foo? The only difference appears to be the presence of a constructor, but I’d expect the reported_class constructor to be called in either case (therefore forcing static instantiation due to use in the constructor). Is there a reason for this in the standard that I’m not aware of, and is this something that can be relied upon?
gcc-4.7.3 displays the same behavior, so I assume that this is something that I"m misunderstanding.
Apparently in the not shown main function you're not instantiating either class.
Then there's no reason for the compiler to generate a default constructor for class foo.
And without that, there's no code that instantiates reported_class<foo>.
Related
This question already has an answer here:
Why can I call base template class method from derived class
(1 answer)
Closed 2 years ago.
I have a template struct which inherits another template struct. It fails compilation in different compilers (in VS2017 and clang on linux). A simple change in the code fixes it.
The code is:
template<typename T>
struct base {
int GetValue2() { return 0; }
};
template<typename T>
struct derived : public base<T>
{
int GetValue() { return GetValue2(); }
};
int main() {
derived<int> a;
return 1;
}
If I change the line
int GetValue() { return GetValue2(); }
to:
int GetValue() { return this->GetValue2(); }
everything compiles just fine.
Does anyone have an idea what's going on?
There is a two-stage name lookup here.
In GetValue(), GetValue2 is not used in a dependent context, so the compiler will look for a name declared at the enclosing namespace scope (which is the global scope here).
It will not look into the base class, since that is dependent and you may declare specializations of Base even after declaring Derived, so the compiler can't really know what i would refer to. If there is no global variable i, then you will get an error message.
In order to make it clear that you want the member of the base class, you need to defer lookup until instantiation time, at which the base class is known. For this, you need to access i in a dependent context, by either using this->i (remember that this is of type Derived*, so is obviously dependent), or using Base::i. Alternatively, Base::i might be brought into scope by a using-declaration.
template<typename T>
struct base {
int GetValue2() { return 0; }
};
template<typename T>
struct derived : public base<T>
{
int GetValue_using() {
using base<T>::GetValue2; // won't compile with gcc, place it outside the function (ok with clang and msvc)
return GetValue2();
}
int GetValue_this() { return this->GetValue2(); }
int GetValue_base() { return base<T>::GetValue2(); }
};
int main() {
derived<int> a;
return 1;
}
Is there a way to get function pointer for a member function that is private inside a class
class A
{
public:
void callMe()
{
cout<<__FUNCTION__<<endl;
}
private:
void fooMem()
{
cout<<__FUNCTION__<<endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
auto fp = &A::fooMem;
return 0;
}
Compiling this in vs 2012 c++ compiler causes below error
error C2248: 'A::fooMem' : cannot access private member declared in class 'A'
see declaration of 'A::fooMem'
I looked into a amazing solution to a similar problem (though I am not very clear how this actually works, if someone can explain that would be great too), Here I want the address of the member not to invoke it.
The reason I am asking for the address is I'll be patching this function with a different implementation.
The class as such is not modifiable, But I can inherit if that can help achieve this.
Since you cannot modify the original class, it would be much easier to simply inherit the class and create a duplicate of the function in a public memberspace.
I tried this out and it works as expected, at least with g++:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
class A
{
public:
void aFunction()
{
cout<<"This is aFunction"<<endl;
}
private:
void anotherFunction()
{
cout<<"This is anotherFunction"<<endl;
}
};
class B: public A
{
public:
void anotherFunction()
{
cout<<"This is also anotherFunction, but it's accessible!"<<endl;
}
};
int main(int argc, char* argv[])
{
A firstClass;
B coach;
firstClass.aFunction();
coach.anotherFunction();
return 0;
}
When I run this code I get the following output:
$ ./a.out
This is aFunction
This is also anotherFunction, but it's accessible!
Proving the compiler understood which version of anotherFunction to use.
I am not able isolate this error in a small sample to demonstrate here, but the even the error message is so self-contradicting that maybe one can have an idea if this is a bug or not, without testing.
I have a struct that is (presumably, publicly) deriving another one, yet clang insists this is implicitly private inheritance:
error: 'next' is a private member of 'base'
note: constrained by implicitly private inheritance here
struct derived_temp <key> : base <derived>
while g++ compiles fine. I have only changed the actual names of the classes to make messages more readable. The code looks like this:
template </*...*/>
struct base : //...
{
private:
//...
public:
template <typename I> I next(I i) const { return /*...*/; }
//...
};
template <typename /*...*/>
struct derived_temp;
struct key { /*...*/ };
using derived = derived_temp <key>;
template <>
struct derived_temp <key> : base <derived>
{
//...
};
I have tried to keep the form of the code exactly the same as in my project, only changing names and commenting out parts of it.
The error is caused by attempting to call function next() on a temporary object of type derived.
My only explanation is that this may be a bug of clang (yet, I cannot reproduce it in a small sample) that forces me to change
struct derived_temp <key> : base <derived>
to the more explicit
struct derived_temp <key> : public base <derived>
Any idea?
Code:
struct T1 {
int x;
};
struct T2 : T1 {
int y;
};
int main( int argc, char * argv[] ) {
T2 t2;
t2.x = 3;
return t2.x;
}
Building/running:
~ clang blah.cc -o blah; ./blah; echo $?
3
~ clang blah.cc -std=c++11 -o blah; ./blah; echo $?
3
In short: defaults to public inheritance.
I spent a little more time on this to get it closer to the OPs code; this is what I put together (please forgive the typos; I'm using an airgapped machine to test this out):
template <class T>
struct base {
T x;
template <typename I> I blah( I i ) const { return i + x.k.y; }
}
template <class T>
struct derived_temp;
struct key { int y; };
using derived = derived_temp<key>;
template <>
struct derived_temp<key> : base <derived> {
int z;
key k;
};
int main( int argc, char * argv[] ) {
derived d;
d.x = 1;
d.k.y = 2;
d.z = 3;
return 0;
}
Built with:
~ clang --version
clang version 3.4 (tags/RELEASE_34/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
~ clang++ test.cc -o test -std=c++11
I get two basic errors (I'm not quoting the full thing since I'd have to manually type it all):
test.cc:3:5: error: field has incomplete type 'derived_temp<key>'
test.cc:21:5: error: no member named 'x' in 'derived_temp<key>'
As I stared at this, trying to understand both your motivation/intent as well as what the errors said, it occurs to me you're attempting to do circular inheritance to define things in a circular fashion that may not even be possible.
Something is a little off there. Structs should use public inheritance by default. Forget the templates for a moment and the using directive.
Test with the simplest code which sets up your suspected fail case:
struct Base
{
int i;
};
struct Derived : Base
{
};
Now try access i from an instance of Derived. If that works, and it should, start to add features until it has all the same kinds of components as your original code.
Right now I don't have clang to test it myself. So I'm just suggesting a way forward.
I'm using Visual Studio 2010.
Why can't I get a pointer to a class method which was "upgraded" to public in a child class?
The following code does not compile:
#include <iostream>
#include <functional>
class Parent {
protected:
void foo() {
std::cout << "Parent::foo()\n";
}
};
class Child : public Parent
{
public:
//void foo() { Parent::foo(); } //This compiles
using Parent::foo; //This does NOT compile
};
int main() {
Child c;
std::function < void () > f = std::bind(&Child::foo, &c);
f();
return 0;
}
It gives the error:
error C2248: 'Parent::foo' : cannot access protected member declared in class 'Parent'
It compiles here.
I think you just forgot to add the C++11 option in you compiler.
For example, with gcc it's -std=c++11 or -std=gnu++11.
EDIT : It seems from here that using alias declaration are not implemented in any Visual Studio version.
In fact, here some people talks about a compiler bug.
The weird thing here is:
c.foo(); // this works fine
std::function < void () > f = std::bind(&Child::foo, &c); // this won't compile
For some reason, Visual Studio won't let you take the address of foo, even though it is a public member of Child declared using plain old C++03 syntax.
std::function<void()> f = std::bind(&Child::foo, &c); // won't compile
auto fp = &Child::foo; // also won't compile
Directly calling the function still works fine:
c.foo(); // compiles OK
Curiously, this means you use VS2010's partial C++11 support to work around a flaw in its C++03 support, by using a lambda to achieve the same effect that your bind expression would have had:
std::function<void()> f = [&c]{ c.foo(); }; // compiles OK!
This code compiles with g++ 4.8.1. Are you using C++11? I get the following output when I run it:
Parent::foo()
In pre c++11,
this 'using' allows to not hide Parent::foo in case like these:
class Parent
{
protected:
void foo() {}
};
class Child : public Parent
{
using Parent::foo; // without this, following code doesn't compile.
public:
// foo(int) hides Parent::foo without the 'using'
void foo(int) { return foo(); }
};
The assertion in the following program gives different results according to the compiler used: in GCC 4.4 the assertions fails, while in CLang does not. It looks like GCC does not like V being private in C. Is this a bug?
#include <cassert>
class V {
public:
virtual ~V() { };
};
template<class T>
class C : public T, private V {
public:
static V* new_() {
return new C();
}
};
struct MyT {
};
typedef C<MyT> C_MyT;
int main(int argc, char** argv) {
V* o2 = C_MyT::new_();
assert(dynamic_cast<C_MyT*> (o2)); // failure in GCC, success in CLang
return 0;
}
g++ appears to be behaving correctly. See Dynamic downcast on private inheritance within private scope which has a good answer describing this.