Can't assign the address of std::list::unique()

John Emmas 161 Reputation points
2021-03-06T09:35:19.3+00:00

According to MSDN 'std::list::unique()' returns type void - so why doesn't the following C++ code compile in VS2019?

Can anyone see a problem with the code? Or suggests a fix / workaround?

#include <list>

using LT = std::list<int>;

using func_void_t = void(LT::*)();
using func_ref_t = LT::reference(LT::*)();
using func_iter_t = LT::iterator(LT::*)();

int main (int argc, char *argv[])
{
// Non-overloaded members
  func_void_t f1 = &LT::reverse;     // Succeeds
  func_void_t f2 = &LT::clear;       // Succeeds
  func_void_t f3 = &LT::sort;        // Succeeds
  func_void_t f4 = &LT::pop_front;   // Succeeds

// Members with overloads
  func_ref_t f6  = &LT::front;       // Succeeds
  func_iter_t f7 = &LT::end;         // Succeeds
  func_void_t f5 = &LT::unique;      // FAILS (error C2440)

  return 0;
}
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,516 questions
0 comments No comments
{count} votes

Accepted answer
  1. Viorel 111.7K Reputation points
    2021-03-06T09:58:20.377+00:00

    Try this workaround:

    . . .
    if constexpr( false ) LT( ).unique( );
    func_void_t f5 = &LT::unique;
    . . .
    

    or

    . . .
    using unused = decltype( std::declval<LT>( ).unique( ) );
    func_void_t f5 = &LT::unique;
    . . .
    
    0 comments No comments

3 additional answers

Sort by: Most helpful
  1. John Emmas 161 Reputation points
    2021-03-06T13:52:54.89+00:00

    Wow! I'd scratched my head for over a week with this but I tried your solution #2 and it seems to fix the problem - many thanks !!

    It'd be really great if you could explain a bit how that solution works....


  2. Igor Tandetnik 1,106 Reputation points
    2021-03-06T15:23:19.98+00:00

    First, std::list::unique returns void in C++17 and earlier, but size_t in C++20: source. Even if you get your program to compile now, it will likely start to break soon.

    Second, it is generally not portable to take an address of a member function of a standard library class:

    [member.functions]/2 For a non-virtual member function described in the C++ standard library, an implementation may declare a different set of member function signatures, provided that any call to the member function that would select an overload from the set of declarations described in this document behaves as if that overload were selected. [Note: For instance, an implementation may add parameters with default values, or replace a member function with default arguments with two or more member functions with equivalent behavior, or add additional signatures for a member function name. —end note]

    So your whole design relies on implementation details.

    What is the original problem you are trying to solve, for which you want to use pointers-to-member? There may be other, portable ways to solve it.

    0 comments No comments

  3. John Emmas 161 Reputation points
    2021-03-06T16:20:34.787+00:00

    Many thanks guys - I appreciate all the help. There's quite a long discussion about this, over on CodeGuru

    In a nutshell, I'm trying to build some code for a library we use here (the library's called Lua). It seems to produce a "customized" version of some general template stuff, like list and vector etc (i.e. it only allows some of the available functions - whereas some extra ones can be added)

    In post #14, 2kaud (the guy who's been helping me) mentions that he'll be passing this on to the VS development team so hopefully they'll become aware of it soon.

    0 comments No comments