c++ - 基类成员函数的所有重载都可以被单个模板化成员函数覆盖和转发吗?

标签 c++ c++11 variadic-templates

我正在尝试创建一个模板包装器类,该类继承自其模板参数并一次性覆盖特定基成员函数的所有重载。这是一个例子:

#include <cassert>
#include <string>   
#include <utility>

template <class T>
class Wrapper: public T {
public:
  template <typename... Args>
  Wrapper<T>& operator=(Args&&... args) {
    return this_member_fn(&T::operator=, std::forward<Args>(args)...);
  }

private:
  template <typename... Args>
  Wrapper<T>& this_member_fn(T& (T::*func)(Args...), Args&&... args) {
    (this->*func)(std::forward<Args>(args)...);
    return *this;
  }   
};

int main(int, char**) {
  Wrapper<std::string> w;
  const std::string s("!!!");
  w = s;
  assert(w == s);
  w = std::string("???");
  assert(w == std::string("???"));
  return 0;
}

想法是 Wrapper<T>::operator= 的模板将在编译时根据其参数选择正确的 T::operator=,然后转发这些参数。如果我用

gcc -std=c++11 -W -Wall -Wextra -pedantic test.cpp -lstdc++

我从 gcc 收到以下投诉:

test.cpp: In instantiation of ‘Wrapper<T>& Wrapper<T>::operator=(Args&& ...) [with Args = {std::basic_string<char, std::char_traits<char>, std::allocator<char> >}; T = std::basic_string<char>]’:
test.cpp:26:24:   required from here
test.cpp:10:69: error: no matching function for call to ‘Wrapper<std::basic_string<char> >::this_member_fn(<unresolved overloaded function type>, std::basic_string<char>)’
test.cpp:10:69: note: candidate is:
test.cpp:15:15: note: Wrapper<T>& Wrapper<T>::this_member_fn(T& (T::*)(Args ...), Args&& ...) [with Args = {std::basic_string<char, std::char_traits<char>, std::allocator<char> >}; T = std::basic_string<char>]
test.cpp:15:15: note:   no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘std::basic_string<char>& (std::basic_string<char>::*)(std::basic_string<char>)’
test.cpp: In member function ‘Wrapper<T>& Wrapper<T>::operator=(Args&& ...) [with Args = {std::basic_string<char, std::char_traits<char>, std::allocator<char> >}; T = std::basic_string<char>]’:
test.cpp:11:3: warning: control reaches end of non-void function [-Wreturn-type]

第 26 行是 w = std::string("???");而第15行是this_member_fn的声明,所以好像是编译器认为的类型func (= std::string::operator= ) 不是它所期待的那个。

有没有办法使用模板化的 operator= 来做到这一点?像我一样,而不是覆盖每个 operator=单独在基类中?

最佳答案

如果您打算当场使用,则无需获取成员(member)地址。这也免除了您寻找要选择哪个重载版本的问题。

template<
    typename U
    , typename std::enable_if<
        std::is_assignable<T&, U>::value
        , int
    >::type = 0
>
Wrapper& operator=(U&& u)
{
    static_cast<T&>(*this) = std::forward<U>(u);
    return *this;
}

强烈建议使用约束(通过 std::enable_if 进行的 SFINAE 测试),否则会像 Wrapper<int> w, v; w = v; 这样简单。尝试分配 Wrapper<int> 将失败到int .有了约束,特殊成员Wrapper& operator=(Wrapper const&);将被正确挑选。

关于c++ - 基类成员函数的所有重载都可以被单个模板化成员函数覆盖和转发吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11195361/

相关文章:

c++ - 模板参数 '(type)0' 与 'EnumValue' 不匹配

c++ - 使用 std::bind 和 std::placeholders 的可变模板工厂

c++ - 没有用于初始化 std::lock_guard<std::mutex> 的匹配构造函数

c++ - 为什么我们不能在模板特化的开始/中间使用可变参数模板(以及如何模拟)?

c++ - 尝试使用unique_ptr的 vector 引用已删除的函数

c++ - 模板类特化和友元类

c++ - `auto pp` 和 `auto *ppp` 有什么区别?

c++ - 扩展默认复制构造函数

c++ - cpp单位的使用方法

c++ - 如何在我的主应用程序中加载一个 dll 会导致 100 个 CPU 负载?