Topic: Concepts and conversions


Author: s.hesp@oisyn.nl ("Sylvester Hesp")
Date: Fri, 4 May 2007 16:11:38 GMT
Raw View
"Douglas Gregor" <doug.gregor@gmail.com> wrote in message
news:1177513356.654845.101050@r3g2000prh.googlegroups.com...
> On Apr 20, 7:07 am, tasjae...@gmail.com wrote:
>> I have a question about how function parameter conversions will work
>> when the function signature is declared in a concept.
> [snip
>> My question is, if a constrained function template uses Pootle as
>> follows:
>>
>>   template <Pootle P>
>>   void g(P&& p) { f(p, X()); }
>>
>> will this work with S as the template parameter? In particular, is a
>> double conversion performed (from X->Y->Z)?
>
> Yes, there is a double-conversion here. The first conversion is
> performed inside the g(), to turn the X into a Y when calling
> Pootle<P>::f. The second conversion occurs inside the concept map
> Pootle<S>.

Is such a double conversion always performed, even if the 1st and 3rd types
(X and Z in the example) are equal? E.g.

struct X { X(Y); };
struct Y { Y(X); };

concept MyConcept<class T> { void f(T, Y); }

struct MyStruct { };
void f(MyStruct, X);
concept_map MyConcept<MyStruct> { };

template<MyConcept T> void foo(T t)
{
    f(t, X());  // #1
    MyConcept<T>::f(t, X());  // #2
};

Would #1 convert X to Y, and then back to X? Or would it first try to
convert X directly to X, skipping the conversion that was introduced by the
signature in the concept, and only if that fails do a double-conversion? Or
would it simply find f(MyStruct,X) in the global scope and use that instead,
bypassing the concept altogether? But in the latter case, what about #2?
N2081 is a bit unclear about this.

- Sylvester Hesp


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: tasjaevan@gmail.com
Date: Fri, 20 Apr 2007 05:07:31 CST
Raw View
I have a question about how function parameter conversions will work
when the function signature is declared in a concept.

Say you have the following types (specifically defined for the
conversions between them):

  struct X {};
  struct Y { Y(); Y(X); };
  struct Z { Z(); Z(Y); };

and a concept which deals with the 'middle' type:

  concept Pootle<class T> { void f(T, Y); }

If I understand correctly, the following type can model this concept:

  struct S {};
  void f(const S&, Z);
  concept_map Pootle<S> {}

since Z is convertible to Y.

My question is, if a constrained function template uses Pootle as
follows:

  template <Pootle P>
  void g(P&& p) { f(p, X()); }

will this work with S as the template parameter? In particular, is a
double conversion performed (from X->Y->Z)?

Thanks

James

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: =?iso-8859-1?q?Pedro_Lamar=E3o?= <pedro.lamarao@gmail.com>
Date: Fri, 20 Apr 2007 11:34:17 CST
Raw View
On 20 abr, 08:07, tasjae...@gmail.com wrote:

> My question is, if a constrained function template uses Pootle as
> follows:
>
>   template <Pootle P>
>   void g(P&& p) { f(p, X()); }
>
> will this work with S as the template parameter? In particular, is a
> double conversion performed (from X->Y->Z)?

For this piece of code:

// begin code

struct X { };
struct Y { Y(); Y(X); };
struct Z { Z(); Z(Y); };

struct S { };

void
f (S const&, Z);

template <typename T>
void
g (T const& t) { f(t, X()); }

void
h () { g(S()); }

//end code

Visual Studio 2005 gives me the error:

------ Build started: Project: tmp2, Configuration: Debug Win32 ------
Compiling...
test.cpp
c:\documents and settings\psilva\meus documentos\visual studio
2005\projects\remoting\tmp2\test.cpp(12) : error C2664: 'f' : cannot
convert parameter 2 from 'X' to 'Z'
        No user-defined-conversion operator available that can perform
this conversion, or the operator cannot be called
        c:\documents and settings\psilva\meus documentos\visual studio
2005\projects\remoting\tmp2\test.cpp(15) : see reference to function
template instantiation 'void g<S>(const T &)' being compiled
        with
        [
            T=S
        ]
Build log was saved at "file://c:\Documents and Settings\psilva\Meus
documentos\Visual Studio 2005\Projects\Remoting\tmp2\Debug
\BuildLog.htm"
tmp2 - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped
==========

I believe the reason is just that only one user-defined conversion is
allowed.

This rule should not be affected by the use of concept maps.

--
 Pedro Lamar   o


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: tasjaevan@gmail.com
Date: Mon, 23 Apr 2007 22:56:38 CST
Raw View
On Apr 20, 6:34 pm, Pedro Lamar   o <pedro.lama...@gmail.com> wrote:
> On 20 abr, 08:07, tasjae...@gmail.com wrote:
>
> > My question is, if a constrained function template uses Pootle as
> > follows:
>
> >   template <Pootle P>
> >   void g(P&& p) { f(p, X()); }
>
> > will this work with S as the template parameter? In particular, is a
> > double conversion performed (from X->Y->Z)?
>
>
> Visual Studio 2005 gives me the error:
>
> ------ Build started: Project: tmp2, Configuration: Debug Win32 ------
> Compiling...
> test.cpp
> c:\documents and settings\psilva\meus documentos\visual studio
> 2005\projects\remoting\tmp2\test.cpp(12) : error C2664: 'f' : cannot
> convert parameter 2 from 'X' to 'Z'
>         No user-defined-conversion operator available that can perform
> this conversion, or the operator cannot be called
>

> <snip>

> I believe the reason is just that only one user-defined conversion is
> allowed.
>

Yes, only a single conversion is allowed in the current language.

>
> This rule should not be affected by the use of concept maps.
>

ConceptGCC also rejects my example code due to the double conversion,
so that would seem to agree with you.

But isn't there something broken about it? My S models Pootle. My g is
using Pootle correctly within a constrained template. Result: syntax
error.

I think a double conversion is correct in this situation. If you look
at N2081 (paragraph 3.3.3), it says that, since

  concept_map Pootle<S> {}

does not provide a definition for f, a forwarding function is
generated. Something like:

  concept_map Pootle<S> { void f(const S& s, Y y) { f(s, y); }}

So there are effectively two functions, each one performing one
conversion.


James






---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: =?iso-8859-1?q?Pedro_Lamar=E3o?= <pedro.lamarao@gmail.com>
Date: Tue, 24 Apr 2007 12:15:28 CST
Raw View
On 24 abr, 01:56, tasjae...@gmail.com wrote:

> I think a double conversion is correct in this situation. If you look
> at N2081 (paragraph 3.3.3), it says that, since
>
>   concept_map Pootle<S> {}
>
> does not provide a definition for f, a forwarding function is
> generated. Something like:
>
>   concept_map Pootle<S> { void f(const S& s, Y y) { f(s, y); }}
>
> So there are effectively two functions, each one performing one
> conversion.

I see your point.
The function f in scope satisfies the concept but doesn't have the
exact signature required, and the language in 3.3.3 tells us this
exact f should be implicitly generated.

But this seems strange.

I would expect that the concept Pootle is fully satisfied by the type
S -- because there is a proper f in scope.
The language on section 3 seems to require that every concept_map
provide this function f for S either explicitly or through an implicit
(forwarding) definition, no matter what.

So what should happen in this case?

struct P { };
void f (P, Z) { }
concept_map Pottle<P> { };

Should this fail because the concept_map will implicitly generate a
new, ambiguous, f?

Am I missing something?
I admit I haven't studied N2081 in full detail.

--
 Pedro Lamar   o


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Douglas Gregor <doug.gregor@gmail.com>
Date: Wed, 25 Apr 2007 11:47:19 CST
Raw View
On Apr 20, 7:07 am, tasjae...@gmail.com wrote:
> I have a question about how function parameter conversions will work
> when the function signature is declared in a concept.
[snip
> My question is, if a constrained function template uses Pootle as
> follows:
>
>   template <Pootle P>
>   void g(P&& p) { f(p, X()); }
>
> will this work with S as the template parameter? In particular, is a
> double conversion performed (from X->Y->Z)?

Yes, there is a double-conversion here. The first conversion is
performed inside the g(), to turn the X into a Y when calling
Pootle<P>::f. The second conversion occurs inside the concept map
Pootle<S>.

ConceptGCC does not properly compile this code, but the code is
correct.

  - Doug

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]