|
From: Daniel Krügler on 11 Apr 2008 09:09 On 11 Apr., 19:50, Gerhard Menzl <clcppm-pos...(a)this.is.invalid> wrote: > Consider: > > #include <algorithm> > #include <vector> > > template <typename Element, > typename Member, > Member (Element::*memPtr)()> > bool lessMember(Element const& left, Element const& right) > { > return (left.*memPtr)() < (right.*memPtr)(); > } This should not compile, because you are attempting to apply a pointer to non-const member function to references to const. Fix this to read: template <typename Element, typename Member, Member (Element::*memPtr)() const> bool lessMember(Element const& left, Element const& right) { return (left.*memPtr)() < (right.*memPtr)(); } > > class C > { > public: > C(int i, long l) : m_i(i), m_l(l) {} > > int GetInt() { return m_i; } > long GetLong() { return m_l; } Given above fix, you also need to modify these member declarations to: int GetInt() const { return m_i; } long GetLong() const { return m_l; } > > private: > int m_i; > long m_l; > }; > > int main() > { > std::vector<C> vc; > > static int const elementCount = 3; > > for (int elem = 0; elem < elementCount; ++elem) > vc.push_back(C(elem, elementCount - elem)); > > // linker error without the following line uncommented > // bool b = lessMember<C, long, &C::GetLong>(vc[0], vc[1]); > > std::sort(vc.begin(), > vc.end(), > lessMember<C, long, &C::GetLong>); > } > > Unless the function template specialization lessMember<C, long, > &C::GetLong> is called explicitly, my compiler (Visual C++ 6.0) does not > instantiate the template and causes a linker error (unresolved > external). Please excuse that I cannot resist to smile a bit, after having read about the VC6 compiler in the context of templates... ;-) > Just taking the address of the specialization in the call to > std::sort does not seem to suffice. Is this one of the many limitations > of this outdated compiler, or does the Standard really not require an > instantiation here? > > According to 14.7.1/2, a "function template specialization is implicitly > instantiated when the specialization is referenced in a context that > requires a function definition to exist". I would have assumed that > taking the address of a function (template specialization) requires its > definition. The standard clearly says that a function must exist in this case. This can be deduced by the combination of [basic.def.odr]/2: "An overloaded function is used if it is selected by overload resolution when referred to from a potentially-evaluated expression." with [over.over]/1: "A use of an overloaded function name without arguments is resolved in certain contexts to a function, a pointer to function or a pointer to member function for a specific function from the overload set. A function template name is considered to name a set of overloaded functions in such contexts.[..]" HTH & Greetings from Bremen, Daniel Kr�gler -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Greg Herlihy on 14 Apr 2008 04:13 On Apr 14, 9:35 am, Gerhard Menzl <clcppm-pos...(a)this.is.invalid> wrote: > > Sorry, the consts were in the original code I compiled, they must have > disappeared in reducing the code to the minimum. Since the error only > occurs at link time, using Comeau online to test the code is not an option. Then use Dinkumware's "Exam-" web-page of C++ compilers: http://dinkumware.com/exam/default.aspx According to that page, Visual C++ 6 and 7 both fail to link your program - whereas Visual C++ 8.0 (both Express and Standard versions) succeed. So a compiler upgrade might be in order. > > The standard clearly says that a function must exist in this case. > > This can be deduced by the combination of [basic.def.odr]/2: > > > "An overloaded function is used if it is selected by overload > > resolution when referred to from a potentially-evaluated expression." > > > with [over.over]/1: > > > "A use of an overloaded function name without arguments is resolved in > > certain contexts to a function, a pointer to function or a pointer to > > member function for a specific function from the overload set. A function > > template name is considered to name a set of overloaded functions in such > > contexts.[..]" > > Thanks for pointing me to these passages, but I find them anything but > clear. Does this really apply to taking the address of the function > template specialization? Yes, see also �14.8.2.2 "Deducing template arguments taking the address of a function template" The C++ program in question invokes the lessMember function specialization - so the compiler needs to instantiate it. Greg -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Daniel Krügler on 14 Apr 2008 12:23 On 14 Apr., 18:35, Gerhard Menzl <clcppm-pos...(a)this.is.invalid> wrote: > Daniel Kr�gler wrote: > > The standard clearly says that a function must exist in this case. > > This can be deduced by the combination of [basic.def.odr]/2: > > > "An overloaded function is used if it is selected by overload > > resolution when referred to from a potentially-evaluated expression." > > > with [over.over]/1: > > > "A use of an overloaded function name without arguments is resolved in > > certain contexts to a function, a pointer to function or a pointer to > > member function for a specific function from the overload set. A function > > template name is considered to name a set of overloaded functions in such > > contexts.[..]" > > Thanks for pointing me to these passages, but I find them anything but > clear. Does this really apply to taking the address of the function > template specialization? Let's unroll it from end to begin: [over.over] provides the rules about "Address of overloaded function" and p.1 (quoted above) just describes the syntactic manifold of taking the pointer to a (free or static member) function, pointer to member function, etc. It clarifies in this context that any function template used like this follows the same rules as a "set of overloaded" functions. The last point is important, because it gives us the correct link to what entity we have to refer for. I assume that you hesitation is based on the fact that [over.over] speaks of a "template name" and not of a "template id". If so, your hesitation is primarily profound, because this paragraph does not *clearly* say whether it wants to include the case of a template with explicitly specified template arguments. But at this point this case is not explicitly excluded. To be sure we have to read a bit further (and I apologize for not providing this information in the first place) in p.2: "If the name is a function template, template argument deduction is done (14.8.2.2), and if the argument deduction succeeds, the resulting template argument list is used to generate a single function template specialization, which is added to the set of overloaded functions considered." Note that this paragraph speaks of "resulting template argument list" which includes the case of explicitly provided arguments. This wording was chosen as part of http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#250 to express exactly this intend. The quote of [basic.def.odr] is relevant, because if defines the term of "usage" and thus implies the existence of the definition of the offending function. Even though you will find a lot of issues regarding [over.over], these are actually all issues which clarify situations that could be interpreted to lead to ambiguities or ill-formed code (E.g. #250 belongs to this category). Obviously the VC6 compiler does not cause this kind of problems here, because according to your description the code *compiles* and is well-formed. There is no doubt, that the expression std::sort(vc.begin(), vc.end(), lessMember<C, long, &C::GetLong>); is "potentially evaluated" and that a given specialization of lessMember *is used*, otherwise this code would not make much sense. Taking all this together I would say that this is a clear compiler or linker error. I hope this explanation was a bit clearer than the first. Greetings from Bremen, Daniel Kr�gler -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
|
Pages: 1 Prev: Avoiding dangling pointers. Next: String literal as template parameter? |