Bug 50711

Summary: [C++0x] substitution failure reports error with result_of
Product: gcc Reporter: Jarryd Beck <jarro.2783>
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED INVALID    
Severity: normal CC: daniel.kruegler
Priority: P3    
Version: 4.7.0   
Target Milestone: ---   
Host: x86_64-unknown-linux-gnu Target: x86_64-unknown-linux-gnu
Build: x86_64-unknown-linux-gnu Known to work:
Known to fail: Last reconfirmed:
Attachments: substitution failure error

Description Jarryd Beck 2011-10-13 02:00:44 UTC
Created attachment 25479 [details]
substitution failure error

The attached file produces an error. I believe that the templated "get" function should fail, leaving the non templated function as the only valid choice, not reporting an error, but choosing the non templated function.

Compiled with:
g++ substitution.cpp -std=gnu++0x -save-temps

gcc -v

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/home/jarrydb/current/soft/install-latest/libexec/gcc/x86_64-unknown-linux-gnu/4.7.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: /home/jarrydb/current/soft/src/gcc-git/configure --prefix=/home/jarrydb/current/soft/install-latest --disable-multilib --enable-languages=c,c++
Thread model: posix
gcc version 4.7.0 20111011 (experimental) (GCC)
Comment 1 Paolo Carlini 2011-10-13 02:15:42 UTC
Unfortunately, I don't think you can use std::result_of for sfinae purposes, if I understand correctly it's a well know annoyance which you have to overcome by open coding with std::declval.
Comment 2 Paolo Carlini 2011-10-13 02:19:27 UTC
Eg, if you simply open the <functional> header you will find plenty of decltype( std::declval... for sfinae, which cannot be replaced by a concise std::result_of
Comment 3 Jarryd Beck 2011-10-13 03:32:05 UTC
The following code works:

struct Tuple
{
  int a, b, c;
};

struct array_get
{
  template <typename T>
  const T&
  operator()(const T& t)
  {
    return t;
  }

  template <typename Array, typename First, typename... Location>
  auto
  operator()(const Array& a, First f, Location... loc)
  //  -> typename std::result_of<array_get(decltype(a[f]), Location...)>::type
    -> decltype(operator()(a[f], loc...))
  {
    return operator()(a[f], loc...);
  }
};

struct Array
{
  int array[5][5][5];

  Array()
  {
    for (int i = 0; i != 5*5*5; ++i)
    {
      reinterpret_cast<int*>(array)[i] = i;
    }
  }

  int get(const Tuple& t)
  {
    return array[t.a][t.b][t.c];
  }

  template <typename... Location>
  //typename std::result_of<array_get(int[5][5][5], Location...)>::type
  auto
  get(Location... loc)
    -> decltype(array_get()(array, loc...))
  {
    return array_get()(array, loc...);
  }
};

int main(int argc, char *argv[])
{
  Array a;
  Tuple t{3,4,1};
  //return a.get(1,2,3);
  return a.get(t);
}
Comment 4 Jonathan Wakely 2011-10-13 08:18:07 UTC
See http://lwg.github.com/issues/lwg-defects.html#1225 and also 1270

result_of cannot be used for SFINAE, it requires that its arguments be a valid expression
Comment 5 Jonathan Wakely 2011-10-13 08:19:28 UTC
(In reply to comment #4)
> result_of cannot be used for SFINAE, it requires that its arguments be a valid
> expression

Should read: it requires that its arguments can form a valid expression
Comment 6 Paolo Carlini 2011-10-13 09:33:50 UTC
Ok, I guess we can close this.