【问题标题】:Calling a templated functor in a class template在类模板中调用模板仿函数
【发布时间】:2021-08-13 01:12:10
【问题描述】:

有什么方法可以调用类模板Foo的函子operator()( int ),如下图(online version

template<typename T>
struct Foo
{
    template<typename U>
    void operator()( int )
    {
    }
};

int main(int argc, char *argv[])
{
    Foo<char> foo;
    foo<bool>( 42 );
}

我在 gcc 4.9.3 中收到错误消息

error: expected primary-expression before ‘bool’
  foo<bool>( 42 );

如果成员函数不是函子并且以::.-&gt; 为前缀,我会在函子前面加上template。没有一些帮助,编译器不知道如何解析这个表达式;作为 foo&lt;int&gt; 类型的匿名对象的仿函数或实例化。

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    它可以使用;

    foo.operator()<bool>( 42 );
    

    运算符最适合推导出的模板参数类型。

    您没有提供足够详细的上下文,作为您可以考虑的替代方案;

    • 使调用运算符成为成员函数,从而允许显式模板类型参数
    • 标签调度机制
    • 接受U 类型作为参数

    例如;

    template<typename U>
    void operator()( int, U&& /*initial*/ )
    {
      // use the initial value of U
    }
    // called as...
    
    foo(42, true); // U is bool in your example
    

    或者只是成员函数;

    template<typename U>
    void my_func( int )
    {
    }
    // called as...
    
    foo.my_fun<bool>( 42 );
    

    【讨论】:

    • “运算符最适合推导出的模板参数类型”——值得记住。不过我忽略了&amp;&amp;
    • @Olumide。使用U&amp;&amp; 参数的想法是,如果类型比原始类型更复杂,则可以使用std::move,或者U&amp;&amp; 也可以绑定到临时类型。一个简单的U 也可以正常工作。
    • c++17这个问题还存在吗?
    • @ar2015 不确定模板推导指南是否会有所作为,我还没有真正有理由使用它们。或者它们是否可以与操作员一起使用。 en.cppreference.com/w/cpp/language/…
    【解决方案2】:

    是的,但它很丑:

    foo.operator()<bool>( 42 );
    

    【讨论】:

      【解决方案3】:

      很遗憾,您需要为此使用foo.operator()&lt;bool&gt;(42);foo&lt;bool&gt; 适用于诸如 C++14 变量模板之类的东西,而不是模板调用运算符。

      您可以做的是标记类型并将其作为参数传递给调用运算符以推断出正确的类型:

      //tag
      template <typename T>
      struct type{};
      
      template<typename T>
      struct Foo
      {
          template<typename U>
          //deduction on the tagged type
          void operator()( type<U>, int )
          {
          }
      };
      
      int main(int argc, char *argv[])
      {
          Foo<char> foo;
          foo( type<bool>{}, 42 );
          //   ^^^^^^^^^^^^ pass tag
      }
      

      您可以为标签使用 C++14 变量模板,让它变得更好:

      template <typename T>
      struct type_t{};
      
      //variable template for nicer usage
      template <typename T>
      type_t<T> type;
      
      template<typename T>
      struct Foo
      {
          template<typename U>
          void operator()( type_t<U>, int )
          {
          }
      };
      
      int main(int argc, char *argv[])
      {
          Foo<char> foo;
          foo( type<bool>, 42 );
          //don't need {}^
      }
      

      【讨论】:

        【解决方案4】:

        遗憾的是,如果函子本身就是一个模板,那么语法会变得更加复杂。以下将失败:

        template <typename Functor, typename ... Args>
        void Foo (Functor & f)
        {
            f.operator()<Args...>();
        }
        
        struct MyFunctor
        {
            template <typename ...>
            void operator () () {}
        };
        
        int main ()
        {
            MyFunctor f;
            Foo(f);
        }
        

        我们必须改为:

        f.template operator()<Args...>();
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-03-06
          • 1970-01-01
          • 2010-12-22
          • 2018-11-12
          • 1970-01-01
          • 1970-01-01
          • 2011-01-10
          相关资源
          最近更新 更多