I have following piece of code:
It compiles without problems under gcc-3.4, gcc-4.3, intel compiler, but fails under MSVC9.
MSVC tells "use of undefined type c_traits<C>, while compiling class template member function void foo<C>::go(void) with C=short.
The point it the compiler tries to install unused member function of unused class, because
this class is just not used at all.
I can work-around the issue by specializing entire class foo instead of specializing
its member function. But the point it that specializing entire class is little bit problematic for me for different reasons.
The big question: what is right?
Is my code wrong and gcc and intel compiler just ignore the issue because they do not install foo fully, or
The code is correct and this is bug of MSVC9 (VC 2008) that it tries to install unused member functions?
The code:
class base_foo {
public:
virtual void go() {};
virtual ~base_foo() {}
};
template<typename C>
struct c_traits;
template<>
struct c_traits<int> {
typedef unsigned int_type;
};
template<typename C>
class foo : public base_foo {
public:
static base_foo *create()
{
return new foo<C>();
}
virtual void go()
{
typedef typename c_traits<C>::int_type int_type;
int_type i;
i=1;
}
};
template<>
base_foo *foo<short>::create()
{
return new base_foo();
}
int main()
{
base_foo *a;
a=foo<short>::create(); delete a;
a=foo<int>::create(); delete a;
}
Both compilers are right here; the behavior for your case is unspecified. ISO C++ 14.7.1[temp.inst]/9:
An implementation shall not implicitly instantiate a function template, a member template, a non-virtual member function, a member class or a static data member of a class template that does not require instantiation. It is unspecified whether or not an implementation implicitly instantiates a virtual member function of a class template if the virtual member function would not otherwise be instantiated.
The reasoning for this is fairly simple: a virtual function requires a vtable entry, and with virtual dispatch, it may be tricky for the compiler to determine whether a given virtual function is actually called or not. Therefore, ISO C++ permits the compilers to do such advanced analysis for the sake of generating smaller code, but does not require it of them - so, as a C++ programmer, you should always assume that all virtual functions will always be instantiated.
The removal of unused functions will occur at linking not at compilation where you are having your error. MSVC may not know who amongst all the compilation units being compiled who will ultimately call that method. It can't know until compilation is complete and until linking occurs. Naturally different compilers may be smarter about this, but I suspect this may be what is happening.
I suspect your specific compiler errors sounds like it is caused by you having only forward declared
template<typename C>
struct c_traits;
you have not fully specified the class. Did you try something as simple as:
template<typename C>
struct c_traits
{
// some default/dummy int type
};
I suspect this would at least stop the compiler from complaining.
EDIT
this is generally wrong for class
templates. Member functions of class
templates aren't supposed to be
compiled (and any errors in their
bodies aren't supposed to be
triggered) unless they're instantiated
The template is instantiated in this case in the form of:
foo<short>
The compiler will treat this as any other class who's methods have potential for external linkage. I haven't heard any special language rule that says that external linkage doesn't apply to templates...?
Related
I didn't expect this to compile but it does. I'm wondering if this is guaranteed to happen or whether it's just compiler-specific. I'm wondering why 'OSInterface::handleOSEvents()' can see the 'InputHandler' class and its member function. If OSInterface is an ordinary class then it doesn't compile, the order of the class definitions must be swapped.
template <typename input_handler_t>
class OSInterface
{
public:
void readOSEvents()
{
input_handler_t::handleKeyDown(5);
}
};
struct InputHandler
{
static void handleKeyDown(int a) {};
};
int main()
{
OSInterface<InputHandler> os;
os.readOSEvents();
}
Edit: I was thinking the compiler must be doing something special with it, because if it instantiates the template class in the order that it's declared then it shouldn't be able to see 'InputHandler' and call its member function. On the other let's say that it instantiates the class right at the bottom of the .cpp then it would be able to see 'InputHandler' but I wouldn't be able to create an object of that class in main().
I'm wondering why 'OSInterface::handleOSEvents()' can see the 'InputHandler' class and its member function.
There is no OSInterface::handleOSEvents() in the example. I assume that you mean OSInterface::readOSEvents().
Because OSInterface is instantiated after InputHandler was defined.
I'm wondering if this is guaranteed to happen or whether it's just compiler-specific.
The program is well-formed. The program will compile with all standard conforming language implementations.
This question already has an answer here:
Why are some functions within my template class not getting compiled?
(1 answer)
Closed 2 years ago.
This C++ code builds successfully:
void h(int *)
{
}
template <typename T>
class A
{
public:
void f()
{
T *val;
h(val);
}
};
int main()
{
A<const int> a;
}
Why?
It is undeniable that A<const int>::f() cannot work.
If you call a.f(), it fails to build as expected.
Why is an instance of A<const int> even allowed to exist then?
I'm not sure how SFINAE applies here.
I'd appreciate a C++ standard quote or a relevant link.
It's allowed to exist because it can still be useful for it to exist.
Consider std::vector, which has a one-argument overload of resize, which default-constructs new elements. Definitely useful! But it's also useful to have a std::vector of some type which isn't default-constructible, when you don't intend to resize it in that way. Forcing all member functions to be available, even those not needed by the user, would artificially restrict the applicability of a class.
There's no sfinae here. If we look closely at the declaration of the function, and not it's implementation:
template <typename T>
class A
{
public:
void f();
};
You can see that there's nothing to tell the compiler that this function should not be part of overload resolution.
If we add a return type containing an expression, this is different:
template <typename T>
class A
{
public:
auto f() -> decltype(void(h(std::declval<T*>())));
};
That's different. Now The compiler need to resolve h(T*) to perform overload resolution. If the substitution fails (the instantiation of the function declaration) then the function is not part of the set.
As for why the code still compiles, take a look at this:
void h(int *)
{
}
template <typename T>
class A
{};
template<typename T>
void f()
{
T *val;
h(val);
}
int main()
{
A<const int> a;
}
It's undeniable that f(A<const int>) cannot work
If you call f(a), it fails to build as expected.
Why is an instance of A<const int> even allowed to exist then?
The answer should become obvious now: the function is never instantiated!
The very same applies for member functions. There is no use to instantiate all member function if you don't use them.
If you look for an official statement that comfirm this behavior, then look no further than the standard itself.
From [temp.inst]/4 (emphasis mine):
Unless a member of a class template or a member template is a declared specialization, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist or if the existence of the definition of the member affects the semantics of the program; in particular, the initialization (and any associated side effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.
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++.
I am using VS Express 2013 trying to compile a c++ project. I've created a template class with some functions. The class and its functions are all in one header file. I've included the file, I've used the class, I've called functions from it, and despite all that visual studio won't compile the classes' functions that I'm not using. I've turned off all optimizations. Do I HAVE to use a function that I've written just to see that it compiles or not?
Here is the function:
void remove(ID id)
{
sdfgsdfg456456456456sfdsdf
}
The function shouldn't compile. And indeed the project won't compile if I do use this function, but if I don't use the function the project will compile, even if I use other functions from within this class.
Is there a fix to this? Will the same thing happen if I implement the function in a .cpp file?
Edit: I neglected to mention it is a template class. I've added that information in.
As revealed in comments, the reason this is happening is because remove() is a function in a class template. The compiler only instantiates template code if it is actually used; if you don't call remove(), it can have all the syntax errors you want and nobody will complain.
More formally, § 14.7.1 of the standard states (emphasis mine):
The implicit instantiation of a class template specialization causes
the implicit instantiation of the declarations, but not the
definitions or default arguments, of the class member functions
And later in the same section:
An implementation shall not implicitly instantiate a function
template, a member template, a non-virtual member function, a member
class, or a static data member of a class template that does not
require instantiation.
(the word "implicit" is key here; if you use explicit template instantiation, the compiler will immediately try to instantiate all members using the indicated type(s) and fail if any doesn't compile)
This is not just an optimization; you can exploit this behavior to instantiate class templates with types that only support a subset of the template's operations. For example, suppose you write a template class that will be used with types that support a bar() operation, and in addition, some will also support baz(). You could do this:
template<typename T>
class Foo
{
private:
T _myT;
public:
void bar()
{
_myT.bar();
}
void baz()
{
_myT.baz();
}
};
Now suppose you have these too:
struct BarAndBaz
{
void bar() {}
void baz() {}
};
struct BarOnly
{
void bar() {}
};
This will compile and run just fine:
void f()
{
Foo<BarAndBaz> foo1;
foo1.bar();
foo1.baz();
Foo<BarOnly> foo2;
foo2.bar();
// don't try foo2.baz()!
// or template class Foo<BarOnly>!
}
If I have a class template and I use a smart pointer to a dynamically allocated instance of a specialized instance, does that cause the entire class template to be defined by the complier or will it also wait for a member function to be called from the pointer before it is instantiated?
template <class T>
class Test {
public:
void nothing();
void operation();
static const int value;
};
template <class T>
const int Test<T>::value = 100;
template <class T>
void Test<T>::nothing() {
/* invalid code */
int n = 2.5f;
}
template <class T>
void Test<T>::operation() {
double x = 2.5 * value;
}
int main() {
std::unique_ptr<Test<int>> ptr = new Test<int>(); // mark1
ptr->operation(); // mark2
return 0;
}
Does the entire class template get instantiated at mark1?
If not does that mean this code will compile correctly and the member function Test::nothing() not be instantiated?
Does the entire class template get instantiated at mark1?
Yes. The class template is implicitly instantiated — only the class template, not all its members.
If not does that mean this code will compile correctly and the member function Test::nothing() not be instantiated?
The not doesn't imply that, rather if nothing() is not used, it is not instantited.
The full answer to this probably depends highly on what compiler you are using.
At //mark1, the compiler will notice that at least portions of the Test<int> class need to instantiated. Whether or not it does it right then, or in a later phase, is up to the compiler designer.
At //mark2, Test<int>.operation() is obviously needed, it is either marked for later instantiation or created on the spot, again depending on what the compiler designers decided.
Since Test<int>.nothing() is never referenced, the compiler has the freedom to instantiate it or not. Some older compilers blindly instantiated the entire class, but I suspect the majority of modern compilers will only instantiate what they can prove to be necessary (or at least that they can't prove is not necessary). Again, though, where that happens within the compiler depends on the way the compiler designers built the compiler.
So as it turns out for the compiler I'm using (MS Visual C++), my supposition was correct that, for the code as presented in the question, the class template member instantiation would not take place at //mark1 but rather at //mark2 and Test<int>.nothing() would not be created by the compiler.
However, it seems I left out a critical part of the issue that I was experiencing. My actual class was a part of a virtual hierarchy, and according to the MSDN help library all virtual members are instantiated at object creation. So in the example above, if both member functions, i.e. operation() and nothing(), are virtual then at //mark2 the compiler would try to generate code for both functions and the validation of nothing() would fail.
http://msdn.microsoft.com/en-us/library/7y5ca42y.aspx
http://wi-fizzle.com/howtos/vc-stl/templates.htm#t9