我有一个类似于此的访客课程:

struct Visitor 
{
    template <typename T>
    void operator()(T t)
    {
        ...
    }

    void operator()(bool b)
    {
        ...
    }
};

清楚地, operator()(bool b) 旨在作为前面模板函数的专业化。

但是,它没有 template<> 我曾经看过它的语法,将其声明为模板专业化。但这确实是编译的。

这是安全的吗?这个对吗?

有帮助吗?

解决方案

您的代码不是模板专业化,而是一个非模板功能。那里有一些差异。非模拟运算符()将优先于模板版本(对于确切的匹配,但是类型转换不会在此进行),但是您仍然可以强制调用模板函数:

class Visitor
{
public: // corrected as pointed by stefanB, thanks
   template <typename T>
   void operator()( T data ) {
      std::cout << "generic template" << std::endl;
   }
   void operator()( bool data ) {
      std::cout << "regular member function" << std::endl;
   }
};
template <> // Corrected: specialization is a new definition, not a declaration, thanks again stefanB 
void Visitor::operator()( int data ) {
   std::cout << "specialization" << std::endl;
}
int main()
{
   Visitor v;
   v( 5 ); // specialization
   v( true ); // regular member function
   v.operator()<bool>( true ); // generic template even if there is a non-templated overload
   // operator() must be specified there (signature of the method) for the compiler to 
   //    detect what part is a template. You cannot use <> right after a variable name
}

在您的代码中没有太大的区别,但是如果您的代码需要传递模板参数类型,它将变得更有趣:

template <typename T>
T g() { 
   return T();
}
template <>
int g() {
   return 0;
}
int g() {
   return 1;
}
int main()
{
   g<double>(); // return 0.0
   g<int>(); // return 0
   g(); // return 1 -- non-templated functions take precedence over templated ones
}

其他提示

您在这里拥有的是功能超载;为了获得模板专业化,您确实需要 template <> 句法。但是,您应该意识到,这两种方法,即使它们似乎似乎相同,也有明显的不同,甚至在选择正确的呼叫函数时,编译器也可能会丢失。列出所有可能的情况将有点太长,但您可能需要检查 Herb Sutter Gotw#49 就此主题而言。

哦,它会编译。它不会是模板函数。您将具有常规的非模板功能,而不是模板专业化。

它是安全的,实际上也可能是您想要的。访问者模式通常通过过载来实现。专门化功能模板 无论如何,这并不是一个好主意。

您所做的不是模板序列化,而是功能超载。这是安全的。

ps很难说是否正确,不知道您要实现的目标。请记住,无论是模板或超载功能,您的操作员都将在编译时间中选择。如果您需要运行时间调度,则需要多态性,而不是超载。好吧,您可能还是知道。以防万一。

你有

  • void operator()(bool b) 那是非模板函数
  • template< typename T > void operator()(T t) 这是一个单独的基本模板,使上述超载

您可以像在 template<> void operator(int i) 只有在 void operator()(bool b) 不匹配。

基本模板的专业化用于选择要调用哪些基本模板方法。但是,在您的情况下,您有一种非策略方法,将首先考虑。

文章 为什么不专门化功能模板? 很好地解释了如何选择该方法。

Sumary:

  1. 非模板功能首先考虑(这是您的普通运算符()(bool))
  2. 函数碱模板第二次检查(这是您的模板函数),选择了最专业的基本模板,然后如果它具有专业化的专业化,则使用专业化的类型,否则基本模板与“正确”类型一起使用(请参阅文章中的解释)

例子:

#include <iostream>
using namespace std;

struct doh
{
    void operator()(bool b)
    {
        cout << "operator()(bool b)" << endl;
    }

    template< typename T > void operator()(T t)
    {
        cout << "template <typename T> void operator()(T t)" << endl;
    }
};
// note can't specialize inline, have to declare outside of the class body
template<> void doh::operator()<>(int i)
{
    cout << "template <> void operator()<>(int i)" << endl;
}
template<> void doh::operator()<>(bool b)
{
    cout << "template <> void operator()<>(bool b)" << endl;
}

int main()
{
    doh d;
    int i;
    bool b;
    d(b);
    d(i);
}

您会收到电话:

operator()(bool b)       <-- first non template method that matches
template <> void operator()(int i)     <-- the most specialized specialization of templated function is called
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top