Can I use using inside a fnc def? - c++

I've a construct of this form:
template<class X>
struct Base
{
X get_data()
{
return X();
}
};
template<class X>
struct Derived : Base<X>
{
X do()
{
auto v = get_data();//this get is from Base
}
};
I tried to use this get as it is shown but I was getting error : there are no arguments to 'get_data' that depend on a template parameter, so a declaration of 'get_data' must be available [-fpermissive]|
Ok so I've tried:
X do()
{
using Base<T>::get_data;
auto v = get_data();//this get is from Base
}
And I've got the following error: 'Derived<T>::Base' is not a namespace. Now, here I've got a problem, because as a matter of fact formally Base being a struct is a namespace (special form of) but anyway, I declared using Base<T>::get_data; outside of any fnc and this compiles. So the Q is: Is that a compiler error or using 'using declaration' is permitted inside a fnc body?

using directives for base class member names only make sense on the class level, where they serve to make names of base class members visible that might otherwise be hidden.
They do not make sense at function scope, and thus aren't allowed there.
What you can do is this:
struct Derived : public Base<X>
{
using Base<X>::get_data;
//...
};
(This is only sensible here because of your template context and the fact that get_data() doesn't depend on any template parameters. In an ordinary class, you wouldn't need this at all if you aren't deliberately hiding the function.)
At function scope, the only using directives that are allowed are those that bring in names from other namespaces for the purpose of argument-dependent lookup.
Also note that do is a C++ keyword.

Replace
using Base<T>::get_data;
with
using Base<X>::get_data;

auto v = this->get_data();

Related

Visibility of members of base template class not directly inherited

The access to members of a template base class requires the syntax this->member or the using directive. Does this syntax extends also to base template classes which are not directly inherited?
Consider the following code:
template <bool X>
struct A {
int x;
};
template <bool X>
struct B : public A<X> {
using A<X>::x; // OK even if this is commented out
};
template <bool X>
struct C : public B<X> {
// using B<X>::x; // OK
using A<X>::x; // Why OK?
C() { x = 1; }
};
int main()
{
C<true> a;
return 0;
}
Since the declaration of the template class B contains using A<X>::x, naturally the derived template class C can access to x with a using B<X>::x. Nevertheless, on g++ 8.2.1 and clang++ 6.0.1 the above code compiles fine, where x is accessed in C with a using that picks up x directly from A
I would have expected that C can not access directly to A. Also, commenting out the using A<X>::x in B still makes the code to compile. Even the combination of commenting out using A<X>::x in B and at the same time employ in C using B<X>::x instead of using A<X>::x gives a code that compiles.
Is the code legal?
Addition
To be more clear: the question arises on template classes and it is about the visibility of members inherited by template classes.
By standard public inheritance, the public members of A are accessible to C, so using the syntax this->x in C one does indeed get access to A<X>::x. But what about the using directive? How does the compiler correctly resolve the using A<X>::x if A<X> is not a direct base of C?
You are using A<X> where a base class is expected.
[namespace.udecl]
3 In a using-declaration used as a member-declaration, each
using-declarator's nested-name-specifier shall name a base class of
the class being defined.
Since this appears where a class type is expected, it is known and assumed to be a type. And it is a type that is dependent on the template arguments, so it's not looked up immediately.
[temp.res]
9 When looking for the declaration of a name used in a template
definition, the usual lookup rules ([basic.lookup.unqual],
[basic.lookup.argdep]) are used for non-dependent names. The lookup of
names dependent on the template parameters is postponed until the
actual template argument is known ([temp.dep]).
So it's allowed on account of the compiler not being able to know any better. It will check the using declaration when the class is instantiated. Indeed, one can put any dependent type there:
template<bool> struct D{};
template <bool X>
struct C : public B<X> {
using D<X>::x;
C() { x = 1; }
};
This will not be checked until the value of X is known. Because B<X> can bring with it all sorts of surprises if it's specialized. One could for instance do this:
template<>
struct D<true> { char x; };
template<>
struct B<true> : D<true> {};
Making the above declaration be correct.
Is the code legal?
Yes. This is what public inheritance does.
Is it possible to allow a template class derived from B to access to x only via this->x, using B::x or B::x? ...
You can use private inheritance (i.e. struct B : private A<X>), and arrange access to A<X>::x only through B's public/protected interface.
Also, if you're worried about having hidden members, you should use class instead of struct and specify the desired visibility explicitly.
Regarding the addition, note that:
(1) the compiler knows what object A<X>::x refers to given some instance of A<X> (because A is defined in the global scope, and X is the template parameter of C).
(2) You do indeed have an instance of A<X> - this is a ponter to a derived class (it doesn't matter if A<X> is a direct base class or not).
(3) The object A<X>::x is visible in the current scope (because the inheritances and the object itself are public).
The using statement is merely syntactic sugar. Once all types are resolved, the compiler replaces following use of x with the appropriate memory address in the instance, not unlike writing this->x directly.
Maybe this example could give you some idea as to why should it be legal:
template <bool X>
struct A {
int x;
};
template <bool X>
struct B : public A<X> {
int x;
};
template <bool X>
struct C : public B<X> {
//it won't work without this
using A<X>::x;
//or
//using B<X>::x;
C() { x = 1; }
// or
//C() { this -> template x = 1; }
//C() { this -> x = 1; }
};
In case of choosing C() { this -> template x = 1; } the last inherited x (B::x) would be assigned to 1 not the A::x.
It can simply be tested by:
C<false> a;
std::cout << a.x <<std::endl;
std::cout << a.A::x <<std::endl;
std::cout << a.B::x <<std::endl;
Assuming that the programmer for struct B was not aware of struct A members, but the programmer of struct c was aware of members of both, it seems very reasonable for this feature to be allowed!
As to why should compiler be able to recognize using A<X>::x; when it is used in C<X> , consider the fact that within the definition of a class/class template all the direct/indirect inherited bases are visible regardless of the type of inheritance. But only the publicly inherited ones are accessible!
For example if it was like:
using A<true>::x;
//or
//using B<true>::x;
Then there would be a problem by doing:
C<false> a;
Or wise versa. since neither A<true> or B<true> is a base for C<false>, therefor visible. But since it is like:
using A<X>::x;
Because the generic term X is used in order to define the term A<X>, it is first deducible second recognizable, since any C<X> (if is not specialized later) is indirectly based on A<X> !
Good Luck!
template <bool X>
struct C : public B<X> {
// using B<X>::x; // OK
using A<X>::x; // Why OK?
C() { x = 1; }
};
The question is why wouldn't that be supported? Because the constrain that A<X> is a base of a specialization of the main template definition of C is a question that can only be answered, and that only makes sense for a particular template argument X?
To be able to check templates at definition time was never a design goal of C++. Many well formed-ness constrains are checked at instanciation time and this is fine.
[Without a true concept (necessary and sufficient template parameter contracts) support no variant of C++ would do significantly better, and C++ is probably too complicated and irregular to have true concepts and true separate checking of templates, ever.]
The principles that makes it necessary to qualify a name to make it dependent does not have anything with early diagnostic of errors in template code; the way name lookup works in template was considered necessary by the designers to support "sane" (actually slightly less insane) name lookup in template code: a use of a non local name in a template shouldn't bind too often to a name declared by the client code, as it would break encapsulation and locality.
Note that for any unqualified dependent name you can end up accidentally calling an unrelated clashing user function if it's a better match for overloading resolution, which is another problem that would be fixed by true concept contracts.
Consider this "system" (i.e. not part of current project) header:
// useful_lib.hh _________________
#include <basic_tool.hh>
namespace useful_lib {
template <typename T>
void foo(T x) { ... }
template <typename T>
void bar(T x) {
...foo(x)... // intends to call useful_lib::foo(T)
// or basic_tool::foo(T) for specific T
}
} // useful_lib
And that project code:
// user_type.hh _________________
struct UserType {};
// use_bar1.cc _________________
#include <useful_lib.hh>
#include "user_type.hh"
void foo(UserType); // unrelated with basic_tool::foo
void use_bar1() {
bar(UserType());
}
// use_bar2.cc _________________
#include <useful_lib.hh>
#include "user_type.hh"
void use_bar2() {
bar(UserType()); // ends up calling basic_tool::foo(UserType)
}
void foo(UserType) {}
I think that code is pretty realistic and reasonable; see if you can see the very serious and non local issue (an issue that can only be found by reading two or more distinct functions).
The issue is caused by the use of an unqualified dependent name in a library template code with a name that isn't documented (intuitivement shouldn't have to be) or that is documented but that the user wasn't interested in, as he never needed to override that part of the library behavior.
void use_bar1() {
bar(UserType()); // ends up calling ::foo(UserType)
}
That wasn't intended and the user function might have a completely different behavior and fails at runtime. Of course it could also have an incompatible return type and fail for that reason (if the library function returned a value unlike in that example, obviously). Or it could create an ambiguity during overload resolution (more involved case possible if the function takes multiple arguments and both library and user functions are templates).
If this wasn't bad enough, now consider linking use_bar1.cc and use_bar2.cc; now we have two uses of the same template function in different contexts, leading to different expansions (in macro-speak, as templates are only slightly better than glorified macros); unlike preprocessor macros, you are not allowed to do that as the same concrete function bar(UserType) is being defined in two different ways by two translation units: this is an ODR violation, the program is ill formed no diagnostic required. That means that if the implementation doesn't catch the error at link time (and very few do), the behavior at runtime is undefined from start: no run of the program has defined behavior.
If you are interested, the design of name lookup in template, in the era of the "ARM" (Annotated C++ Reference Manual), long before ISO standardization, is discussed in D&E (Design and Evolution of C++).
Such unintentional binding of a name was avoided at least with qualified names and non dependent names. You can't reproduce that issue with a non dependent unqualified names:
namespace useful_lib {
template <typename T>
void foo(T x) { ... }
template <typename T>
void bar(T x) {
...foo(1)... // intends to call useful_lib::foo<int>(int)
}
} // useful_lib
Here the name binding is done such that no better overload match (that is no match by a non template function) can "beat" the specialization useful_lib::foo<int> because the name is bound in the context of the template function definition, and also because useful_lib::foo hides any outside name.
Note that without the useful_lib namespace, another foo that happened to be declared in another header included before could still be found:
// some_lib.hh _________________
template <typename T>
void foo(T x) { }
template <typename T>
void bar(T x) {
...foo(1)... // intends to call ::foo<int>(int)
}
// some_other_lib.hh _________________
void foo(int);
// user1.cc _________________
#include <some_lib.hh>
#include <some_other_lib.hh>
void user1() {
bar(1L);
}
// user2.cc _________________
#include <some_other_lib.hh>
#include <some_lib.hh>
void user2() {
bar(2L);
}
You can see that the only declarative difference between the TUs is the order of inclusion of headers:
user1 causes the instanciation of bar<long> defined without foo(int) visible and name lookup of foo only finds the template <typename T> foo(T) signature so binding is obviously done to that function template;
user2 causes the instanciation of bar<long> defined with foo(int) visible so name lookup finds both foo and the non template one is a better match; the intuitive rule of overloading is that anything (function template or regular function) that can match less argument lists wins: foo(int) can only match exactly an int while template <typename T> foo(T) can match anything (that can be copied).
So again the linking of both TUs causes an ODR violation; the most likely practical behavior is that which function is included in the executable is unpredictable, but an optimizing compiler might assume that the call in user1() does not call foo(int) and generate a non inline call to bar<long> that happens to be the second instanciation that ends up calling foo(int), which might cause incorrect code to be generated [assume foo(int) could only recurse through user1() and the compiler sees it doesn't recurse and compile it such that recursion is broken (this can be the case if there is a modified static variable in that function and the compiler moves modifications across function calls to fold successive modifications)].
This shows that templates are horribly weak and brittle and should be used with extreme care.
But in your case, there is no such name binding issue, as in that context a using declaration can only name a (direct or indirect) base class. It doesn't matter that the compiler cannot know at definition time whether it's a direct or indirect base or an error; it will check that in due time.
While early diagnostic of inherently erroneous code is permitted (because sizeof(T()) is exactly the same as sizeof(T), the declared type of s is illegal in any instantiation):
template <typename T>
void foo() { // template definition is ill formed
int s[sizeof(T) - sizeof(T())]; // ill formed
}
diagnosing that at template definition time is not practically important and not required for conforming compilers (and I don't believe compiler writers try to do it).
Diagnostic only at the point of instantiation of issues that are guaranteed to be caught at that point is fine; it does not break any design goal of C++.

C++ 'using' and 'using typename' in a header file

In the C++ code below, could somebody explain what each of these lines mean in the private section? I have tried looking it up, but I still cannot figure out what they do.
I understand that using is the equivalent to typedef in C. So:
using the_graph = graph<T_node, T_edge1, T_allocator, T_size>;
Means that you use the_graph.
But, in this instance, why would you call the scope resolution operator on it?
I don't think that it is any of the 4 methods described here.
template <class T_node, class T_edge1, class T_edge2, class T_allocator, class T_size = uint32_t>
class graph : private virtual graph<T_node, T_edge1, T_allocator, T_size>, private virtual graph<T_node, T_edge2, T_allocator, T_size>
{
public:
using the_graph = graph<T_node, T_edge1, T_allocator, T_size>;
private:
using typename the_graph::node_list_iterator;
using the_graph::node_begin;
};
The using directive is used to bring a name into the current scope that otherwise is not.
Example:
struct Foo
{
struct Bar {};
};
int main()
{
Bar b1; // Not ok. Bar is not in scope yet.
using Foo::Bar;
Bar b2; // Ok. Bar is now in scope.
}
When a name is dependent upon a template parameter, the standard requires that you use the elaborate form
using typename the_graph::node_list_iterator;
After that line, you can use node_list_iterator as a typename.
Had the_graph not been a class template, you could have used the simpler form
using the_graph::node_list_iterator;
Further reading: Where and why do I have to put the "template" and "typename" keywords?
Those using make visible the associated name and avoid ambiguity.
Both bases should have type node_list_iterator and method(s) node_begin.
Inside the definition and the declaration of a template, the keyword typename is used to specify that the qualified-id (ie some_name::some_member) is a type and not a variable. This keyword is necessary before template instantiation, because the compiler does not know the definition of some_name, and without typename it would supposes that some_member is a variable (or function).
Then the using directive using typename::node_list_iterator make node_list_iterator privately accessible from the graph class.

Can class-local types be used in template classes before they are defined

I have a situation where I've got a template class that really just exposes one public function, and uses a locally-defined struct used for internal state which I don't want cluttering up the public section of my header. For instance:
template <class T>
class MyClass {
public:
struct InternalState {
// lots of noisy stuff I don't want to see in the public section
};
void userCallableFunction() {
InternalState state;
doPrivateStuff(state);
}
private:
doPrivateStuff(InternalState& state) {
// ok for the internals to go here
}
};
I want to push the definition of InternalState down into the private section as the client of the class doesn't need to see it. I want to reduce the noise so it looks like this:
template <class T>
class MyClass {
public:
// only the stuff the client needs to see here
void userCallableFunction() {
InternalState state;
doPrivateStuff(state);
}
private:
// fine for the private noise to be down here
struct InternalState {
};
...
};
The question is: is it legal to do this? ie declare InternalState after it's used in userCallableFunc() ? I know that you can't do this for non-inlined/templated functions, but which rules apply for inline/template functions?
EDIT:
I've tried this in Visual Studio 2010, Clang 4.1 and gcc 4.8.1 (sample in IdeOne, and also a non-templated but inlined case) and it builds successfully for all. So the issue is, is it safe and portable to do this? Please provide references rather than just saying 'no you can't do this'.
As an unqualified-id (no ::) and not being of a syntax that it could be interpreted as a function, where ADL could apply, the name InternalState in the statement
InternalState state;
is looked up using normal unqualified lookup (lookup for unqualifed names).
For unqualified names inside the body of a member function, a special rule applies, see [basic.lookup.unqual]/8
For the members of a class X, a name used in a member function body [...], shall be declared in one of the following ways:
before its use in the block in which it is used or in an enclosing block (6.3), or
shall be a member of class X or be a member of a base class of X (10.2), or
Note that this imposes an ordering on the unqualified lookup: First, the enclosing blocks are searched, then, if nothing has been found, the class members are searched. Also note: as InternalState in this context is not dependent on a template-parameter, the base class scope won't be searched (if there was a base class).
The important part is a bit subtle, unfortunately: shall be a member of class X does not imply shall be declared before the member function body. For example,
struct X
{
int meow()
{
return m; // (A)
}
int m;
} // (B)
;
In the line (A), the name m cannot be found in the current block (or any enclosing blocks, blocks are compound-statements, not just any {}). Therefore, it is looked up in the whole set of members of X. This is only possible once X has been completed, i.e. at the point (B).
The same applies to names that refer to nested classes -- after all, name lookup needs to find out what kind (e.g. function, variable, type) of entity the name refers to. Also, lookup for non-elaborated names IIRC doesn't discriminate between these kinds.
Unfortunately, that's the best I can find right now :/ I'm not happy as it's quite subtle and only answers the question indirectly.
You can only forward declare InternalState and then use pointers or references to it before the compiler sees the definition:
template <class T>
class MyClass {
public:
// only the stuff the client needs to see here
void userCallableFunction() {
std::unique_ptr<InternalState> state = createInternal();
doPrivateStuff(*state);
}
private:
void doPrivateStuff(InternalState const&);
// fine for the private noise to be down here
struct InternalState {
};
std::unique_ptr<InternalState> createInternal() {
return std::make_unique<InternalState>();
}
};
It is similar to the PIMPL idiom, so you might want to look this up.

decltype in class method declaration: error when used before "referenced" member is declared

Consider the following code:
struct test {
auto func() -> decltype(data) {} // ERROR
int data;
};
int main() {
test t;
t.func();
}
It gives the following error:
main.cpp:2:29: error: 'data' was not declared in this scope
auto func() -> decltype(data) {}
However, if I place data above func(), it gives out no error (live code):
struct test {
int data;
auto func() -> decltype(data) {}
};
...
And so my question is, why is decltype not considering members declared after it (when decltype is used in a method declaration, not in the definition)? I also want to know if there are any change in this behavior in future iterations of the language standard.
Please note that I'm asking this because I was expecting decltype to behave differently. My coding convention is to place class data members below the class functions. Surely this different behavior would affect how I organize my class members. I would be very grateful if you can provide any workaround that would preserve my coding convention.
The trailing return type is part of the member function declaration, which does not have access to data members or member functions declared after it, unlike the member function definition, which does. I am not aware of any change in this behaviour in C++14.
See 3.4.1-7 of the C++11 standard, Unqualified name look-up:
A name used in the definition of a class X outside of a member function body or nested class definition
shall be declared in one of the following ways:
before its use in class X or be a member of a base class of X (10.2), or...
(emphasis mine)

Why class forward declaration is not allowed in function scope?

Below code works fine:
template<typename T> class X {};
class A; // line-1
void foo(); // line-2
int main ()
{
X<A> vA;
}
class A {};
void foo() {}
Let line-1 and line-2 are moved inside main(). The function doesn't get affected but the class A forward declaration doesn't work and gives compiler error:
error: template argument for template<class T> class X uses local
type main()::A
What you can observe is happening because, in C++, you can define classes inside functions.
So, if you place class A; in main, you are forward-declaring a class in scope of this function (i.e. class main::A), not in global scope (class A).
Thus, you are finally declaring an object of type X with a template argument of undefined class (X<main::A>).
error: template argument for template class X uses local type main()::A
This is the real problem - using a local type. In C++03 you cannot use local types as template arguments, because nobody had figured out how to name the resulting types.
What if you have several class A in several overloaded functions (again using the same name) - would the resulting X<A>'s then be the same type, or different types? How would you tell them apart?
In C++03 the standard passed on this, and just said "Don't do that!".
The problem was resolved in C++11 by deciding that X<A> using a local type A would be the same as if A had been declared in an anonymous namespace outside of the function, like
namespace
{
class A
{ };
}
int main()
{
X<A> vA;
}
So, with a newer compiler (or using a -std=cpp11 option), you can use a local class, and we also know what it means.
However, forward declaring a type inside a function still doesn't mean the same as forward declaring it in another scope. They will just be different types.