代码之家  ›  专栏  ›  技术社区  ›  olq_plo

C++中方法参数类型的静态内省[复制]

  •  0
  • olq_plo  · 技术社区  · 6 年前

    我想创建一个模板类,它保存另一个类的实例,并转发其中一个 foo

    template <typename Inner>
    class Outer {
    private:
      Inner inner;
    
    public:
    
      // To-do: replicate foo method of Inner with identical signature,
      // how to pick correct T?
      void foo(T arg) { inner.foo(arg); }
    
    };
    

    我可以看到两个经典的解决方案,但有没有一个更好的现代元编程解决方案?

    • 具有部分保护接口的继承: Outer 可以公开继承 Inner protected ,好的,但是它也紧密地耦合了 外部 所有类型的 上课。公共接口 可通过中的公共方法任意扩展 内部 ,这是不需要的。
    • template <typename T> void foo(T&& arg) { inner.foo(std::forward<T>(arg)); } . 这是参数的完美转发,但是如果用户调用 有了错误的参数,错误报告 Inner::foo Outer::foo . 这会破坏 外部
    2 回复  |  直到 6 年前
        1
  •  4
  •   Igor Tandetnik    6 年前

    可能是这样的:

    template <typename Inner>
    class Outer : private Inner {
    public:
      using Inner::foo;
    };
    

    Demo

        2
  •  0
  •   Richard Hodges    6 年前

    #include <string>
    
    // a type which yields the type we gave it
    template<class T> struct passer 
    { 
        using type = T; 
    };
    
    // an easy-to-use alias
    template<class T> using pass_t = typename passer<T>::type;
    
    // example
    template <typename Inner>
    class Outer {
    private:
      Inner inner;
    
    public:
    
      // To-do: replicate foo method of Inner with identical signature,
      // how to pick correct T?
      // Ans: with a pass_t
        template<class T>
        auto foo(T&& arg) 
        -> pass_t<decltype(this->inner.foo(std::forward<T>(arg)))>
        {
           return inner.foo(std::forward<T>(arg)); 
        }
    
    };
    
    
    struct Bar
    {
        void foo(std::string const& thing);
    };
    
    struct Baz
    {
        int foo(int thing) { return thing * 2; };
    };
    
    int main()
    {
    
        auto o = Outer<Bar>();
        o.foo(std::string("hi"));
        o.foo("hi");
    
        int i = 1;
    
        /* - uncomment for error
        o.foo(i);
    
        note the nice error message on gcc:
            <source>:41:7: error: no matching member function for call to 'foo'
            <source>:19:10: note: candidate template ignored: substitution failure [with T = int]: reference to type 'const std::string' (aka 'const basic_string<char>') could not bind to an lvalue of type 'int'
        */
    
    // same here:
    //    o.foo(1);
    
    // but this is fine
        auto o2 = Outer<Baz>();
        auto x = o2.foo(2);
    
        // and this is not
        // note: candidate template ignored: substitution failure [with T = char const (&)[6]]: cannot initialize a parameter of type 'int' with an lvalue of type 'char const[6]'
    //    auto y = o2.foo("dfghj");
    
    }
    

    此处链接: https://godbolt.org/g/UvsrbP