Deducing address of template class's overloaded method results in "error: expected primary-expression before ‘decltype’"

Deducing address of template class's overloaded method results in "error: expected primary-expression before ‘decltype’"

我正在尝试寻找类型然后分配方法,例如:

decltype(std::addressof(&std::vector<int>::push_back<int&&>)) x =
&std::vector<int>::push_back;

我遇到了以下错误:

error: expected primary-expression before ‘decltype

以上代码只是一个最小的例子。实际上,方法的地址将连同其类型一起传递给模板 class。即它也可以是 &std::set<T>::insert<T&&>。因此 auto 可能不是一个选项。
伪代码见:

template<typename Type, // <-- int, float
         template<typename...> class Container, // <-- std::vector, std::set
         typename Method_t,  // <-- decltype(push_back(T&&), insert(T&&))
         Method_t Method>  // <-- push_back(T&&), insert(T&&)
struct Wrap { ... };

#define WRAP(TYPE, CONTAINER, METHOD) \
  Wrap<TYPE, CONTAINER, decltype(&CONTAINER<TYPE>::METHOD<TYPE&&>), &CONTAINER<TYPE>::METHOD>

用法

WRAP(int, std::vector, push_back); // uses `push_back(int&&)`
WRAP(float, std::set, insert);  // uses `insert(float&&)`

推导模板class重载成员方法地址的正确方法是什么?

在我的例子中,Method_t 应该是 push_backinsertpush_frontpushT&& 仅重载版本。
这个 Qn 没有帮助:Address of templated member function

首先,std::addressof 获取 对象的地址 ,而不是成员的地址(在成员指针的意义上)。

其次,std::vector<int>::push_back不是模板。

第三,在获取函数地址时控制重载决议,使用强制转换符号:

static_cast<void (std::vector<int>::*)(int&&)>(&std::vector<int>::push_back)
//          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
//          overload                            name of overload set

截至今天,无法自动推断重载函数 本身。需要在左侧指定其完整签名,以便编译器能够推断出适当的类型。
示例:对于以下 2 个函数:

void C::foo (int);
void C::foo (double);

必须提到 LHS 上的完整原型,

void (C::*method)(int) = &C::foo;  // OK

但不幸的是我们不能做类似的事情,

auto method = &C::foo(int);  // not allowed

因此,无论 Qn 中要求什么,都不可能以其当前形式实现。


但如果要求稍作调整,则可以推导出 return 类型并仍然达到最终预期的结果。
struct Wrap:

的语法略有改动
template<typename Type,
         template<typename...> class Container,
         typename Return,  // <--- changed
         Return (Container<Type>::*Method)(Type&&)>  // <--- full definition
struct Wrap { ... }

使用上面更改的代码,我们不需要推导整个方法的类型,我们只需要推导"return type"。正如已在 Qn 中指定的那样,该参数已知为 Type&&。现在 WRAP 宏看起来像这样:

#define WRAP(TYPE, CONTAINER, METHOD) \
  Wrap<TYPE, CONTAINER, decltype(((CONTAINER<TYPE>*)nullptr)->METHOD(TYPE())), &CONTAINER<TYPE>::METHOD>

用法:

WRAP(int, std::vector, push_back) wrap;

申请Demo.