Is this forwardable correct? It compiles success on my gcc

65 views
Skip to first unread message

ejsvifq mabmip

unread,
Jun 1, 2016, 4:18:56 PM6/1/16
to SG8 - Concepts
 template<typename T,typename U>
 concept bool forwardable = requires(U u)
 {
  {T(u)};
 };

 class name
 {
  std::string str;
 public:
  template<forwardable<std::string> T>
  name(T &&_s):str(std::forward<T>(_s)){}
  const std::string& string() const
  {
   return str;
  }
 };
http://coliru.stacked-crooked.com/a/4685811cc29a2dda
Message has been deleted

Casey Carter

unread,
Jun 1, 2016, 4:35:12 PM6/1/16
to SG8 - Concepts
The syntax of the concept is valid, but it's not doing what you think it is. When performing concept resolution for a partial-concept-id, e.g. forwardable<std::string> in your constructor definition, the "wildcard" goes into the first parameter of the concept. So this:

template<forwardable<std::string> T>
name
(T &&_s):str(std::forward<T>(_s)){}

is a constructor that accepts any type that can be constructed *from* a std::string, not the intended constructor that accepts any type that can be used to construct a std::string. Also, the "u" in the expression "T(u)" is always an lvalue, when the intent is to perfect forward the value category of the expression passed to the name constructor. What you want is:

 template<typename T,typename U>
 
concept bool forwardable = requires(T&& t)
 
{
  U
(static_cast<T&&>(t));
 
};

ejsvifq mabmip

unread,
Jun 1, 2016, 4:35:17 PM6/1/16
to SG8 - Concepts
Here is the issue:




On Tuesday, February 2, 2016 at 5:49:30 PM UTC+8, eulo...@live.com wrote:
class f
{
 std
::string __name;
public:
 f
(const std::string& _name):__name(_name){}
 f
(std::string&& _name):__name(std::move(_name)){}
 
const std::string& name() const
 
{
 
return __name;
 
}
};



However, it just chaotic when parameter numbers are more than 1.  The function will be written for 2^n times to handle both const T& or T&& problem.

Is this better by passing T directly? I think this method is satisfied basic exception safe.
class f
{
 std
::string __name;
public:
 f
(std::string _name):__name(std::move(_name)){}
 
const std::string& name() const
 
{
 
return __name;
 
}
};



I think a standardize Forwardable<T,U> is better to solve this issue. 

Casey Carter

unread,
Jun 1, 2016, 4:40:53 PM6/1/16
to SG8 - Concepts
On Wednesday, June 1, 2016 at 1:35:12 PM UTC-7, Casey Carter wrote:
 template<typename T,typename U>

 
concept bool forwardable = requires(T&& t)
 
{
  U
(static_cast<T&&>(t));
 
};


or equivalently:
template<typename T, typename U>
concept bool forwardable = requires (T&& t) {

ejsvifq mabmip

unread,
Jun 1, 2016, 5:29:17 PM6/1/16
to SG8 - Concepts
Oh, it looks great.

ejsvifq mabmip

unread,
Jun 1, 2016, 5:40:42 PM6/1/16
to SG8 - Concepts

I have a better version.

 template<typename T,typename ...Args>
 
concept bool forwardable = requires(Args&&... args)
 
{
 
{T(std::forward<Args>(args)...)}
 
};


On Thursday, June 2, 2016 at 4:40:53 AM UTC+8, Casey Carter wrote:

Vicente J. Botet Escriba

unread,
Jun 2, 2016, 2:06:52 PM6/2/16
to conc...@isocpp.org
Le 01/06/2016 à 23:40, ejsvifq mabmip a écrit :

I have a better version.

 template<typename T,typename ...Args>
 
concept bool forwardable = requires(Args&&... args)
 
{
 
{T(std::forward<Args>(args)...)}
 
};


I believe this is again wrong. The variadic part shoul dbe at the begining.

I don't know if the following is allowed or not

    template<typename ...Ts,typename U>
    concept bool forwardable = requires(Ts &&... ts)
    {
        U(std::forward<Ts>(ts)...);
    };

For the information it results in a Segmentation fault
prog.cc:8:47: internal compiler error: Segmentation fault
  concept bool forwardable = requires(Ts &&... ts)

http://melpon.org/wandbox/permlink/b6O0u8Yh83xhfdV1

Maybe I did something wrong.

Vicente
Reply all
Reply to author
Forward
0 new messages