C++ 中方法参数类型的静态自省

Static introspection of method argument type in C++

我想制作一个模板化的 class,它包含另一个 class 的实例,并使用正确的参数类型转发其中一个 foo 方法。是否有一种聪明的元编程方式来执行内部方法的 "perfect forwarding" ?

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); }

};

我可以看到两个 classic 解决方案,但是有更好的现代元编程解决方案吗?

也许是这样的:

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

Demo

这是给出几乎完美错误消息的一种方法:

#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");

}

Link 这里:https://godbolt.org/g/UvsrbP