【问题标题】:Passing template function pointer to template as template parameter is too verbose将模板函数指针作为模板参数传递给模板过于冗长
【发布时间】:2014-05-29 10:26:27
【问题描述】:
template<class T, class... TA> Uptr<T, TA> makeUniquePtr(/*...*/) { /*...*/ };
template<class T, class... TA> Sptr<T, TA> makeSharedPtr(/*...*/) { /*...*/ };

template<typename TFPType, TFPType TFP> void func(/*...*/) { /*...*/ }

template<class T, class... TA> void implementation1(/*...*/)
{
    // Can this be reduced to func<&makeUniquePtr, T, TA...>?
    func<decltype(&makeUniquePtr<T, TA...>), &makeUniquePtr<T, TA...>>(/*...*/);
}

template<class T, class... TA> void implementation2(/*...*/)
{
    // Can this be reduced to func<&makeSharedPtr, T, TA...>?
    func<decltype(&makeSharedPtr<T, TA...>), &makeSharedPtr<T, TA...>>(/*...*/);
}

调用func&lt;/*...*/&gt;(/*...*/) 非常冗长。有没有办法简单地调用

func<&makeSharedPtr, T, TA...>(/*...*/)

并在内部使用

&makeSharedPtr<T, TA...>

不让用户指定两次?

【问题讨论】:

  • 尝试使用宏。函数模板本身不能是模板参数。
  • @Constructor:宏是我最后的手段——我希望有一种方法可以在不使用预处理器的情况下达到我想要的结果。
  • 用辅助类模板包装makeXXXPtr函数模板(使其成为此类模板的静态方法)。类模板可以是模板的参数。

标签: c++ templates c++11 parameters function-pointers


【解决方案1】:

创建一个共享 maker 无状态函数对象类,如 std::less,但本身没有 template 参数:取而代之的是 operator() 完美转发到您的 template 函数。

传递它而不是你的函数指针。

如果您需要传递给它的 template 参数,请为其创建一个 static 方法,或者让整个 template class 接受参数并在 operator() 中使用它们。

这是一个后期绑定 template 参数的示例 (live example):

#include <iostream>

// test stubs:
template<typename... Ts>
using UPtr = int;
template<typename... Ts>
using SPtr = double;

template<typename T, typename...TA>
UPtr<T,TA...> makeUniquePtr() {
  std::cout << "makeUniquePtr\n";
  return {};
}
template<typename T, typename...TA>
SPtr<T,TA...> makeSharedPtr() {
  std::cout << "makeSharedPtr\n";
  return {};
}

// perfect forwarding make static functions passed by class name:
struct unique_ptr_maker {
  template<typename T, typename...TA, typename...Args>
  static UPtr<T, TA...> make(Args&&...args) {
    return makeUniquePtr<T, TA...>( std::forward<Args>(args)... );
  }
};
struct shared_ptr_maker {
  template<typename T, typename...TA, typename...Args>
  static SPtr<T, TA...> make(Args&&...args) {
    return makeSharedPtr<T, TA...>( std::forward<Args>(args)... );
  }
};

// your `func`.  It can take args or whatever:    
template<typename maker, class T, class... TA> void func() {
  std::cout << "func\n";
  maker::template make<T, TA...>();
}

// a sample of implementation 1 and 2:
template<class T, class... TA> void implementation1()
{
  func<unique_ptr_maker, T, TA...>();
}
template<class T, class... TA> void implementation2()
{
  func<shared_ptr_maker, T, TA...>();
}
// and, to test, always instantiate:
int main() {
  implementation1<int, double>();
  implementation2<int, char>();
  return 0;
}

大部分功能都被删除了,因为您没有详细说明它在您的问题中应该做什么。

【讨论】:

    【解决方案2】:

    根据你的名字对预期用途做出一些假设,我会尝试这样的事情:

    template<class T>
    struct makeUniquePtr {
        template<class... TA>
        Uptr<T, TA> operator()(TA&&...) const { /*...*/ }
    };
    
    template<class T>
    struct makeSharedPtr {
        template<class... TA>
        Sptr<T, TA> operator()(TA&&...) const { /*...*/ }
    };
    
    template<class F> void func(/*...*/) { /*...*/ }
    
    template<class T, class... TA> void implementation1(/*...*/)
    {
        func<makeUniquePtr<T>>(/*...*/);
    }
    
    template<class T, class... TA> void implementation2(/*...*/)
    {
        func<makeSharedPtr<T>>(/*...*/);
    }
    

    Yakk's solution不同,这里的参数TA...是自动推导出来的,std::make_unique等也是如此。

    编辑 我对 Yakk 解决方案的引用是在编辑该解决方案之前进行的。我现在看到它被扩展了。

    【讨论】:

      猜你喜欢
      • 2015-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-10
      • 2011-09-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多