Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 模板专业化是否需要模板<&燃气轮机;语法?_C++_Templates_Syntax_Template Specialization - Fatal编程技术网

C++ 模板专业化是否需要模板<&燃气轮机;语法?

C++ 模板专业化是否需要模板<&燃气轮机;语法?,c++,templates,syntax,template-specialization,C++,Templates,Syntax,Template Specialization,我有一个类似这样的访客类: struct Visitor { template <typename T> void operator()(T t) { ... } void operator()(bool b) { ... } }; struct访问者 { 模板 void运算符()(T) { ... } void运算符()(布尔b) { ... } }; 显然,操作符()(bool b)旨

我有一个类似这样的访客类:

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

    void operator()(bool b)
    {
        ...
    }
};
struct访问者
{
模板
void运算符()(T)
{
...
}
void运算符()(布尔b)
{
...
}
};
显然,
操作符()(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
}
类访问者
{
public://根据stefanB的观点更正,谢谢
模板
void运算符()(T数据){
std::你有吗

  • void操作符()(bool b)
    这是非 模板函数
  • 模板无效
    运算符()(T)
    这是一个单独的 重载 在上面
您可以对第二个操作符进行完全专门化,如
模板void操作符(inti)
中所述,只有当
void操作符()(bool b)
不匹配时才会考虑该操作符

基本模板的专门化用于选择要调用的基本模板方法。但是,在您的情况下,将首先考虑非模板方法

这篇文章很好地解释了如何选择这种方法

在sumary:

  • 非模板函数是 先考虑一下(这是你的平原 运算符()
  • 检查函数基模板 第二(这是你的模板 函数),然后选择最专门化的基本模板,如果它具有专门化的确切类型,则使用专门化,否则基本模板将与“正确”类型一起使用(请参阅本文中的说明)
  • 例如:

    #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);
    }
    
    #包括
    使用名称空间std;
    结构doh
    {
    void运算符()(布尔b)
    {
    
    在某些情况下,它的行为会有所不同吗?这是一个潜在的错误,还是糟糕的风格?通常,这是正确的做法。通常,您应该更喜欢纯重载而不是函数模板专用化。这种行为更可预测。您错过了参数括号:template void doh::operator()(bool b)(注意“”我插入了),注意他(sutter)明确指出选择了最专业化的基本模板。不是“最匹配专业化的模板”也不是“模板化函数最专业化的模板”。解析明确只考虑主(基本)模板。这称为“函数模板的偏序”在标准的14.6.6.2中有描述。关于基础模板的选择,你是对的,我想我在我的解释(惰性键入?)中短路了它,我想说的是,选择了最专业化的基础模板,然后如果它对使用专门化的确切类型进行了专门化,则基础模板将与“正确”类型一起使用gcc3.3.3中带括号的模板void doh::operator()(bool b)和不带表单的模板void doh::operator()(bool b)编译并给出了相同的结果,但@dribeas对示例的复制/粘贴仍然会给出错误:非命名空间范围中的显式专门化“struct doh”等等-这就是我所指的(并且因为方法都是私有的,但这是附带说明的),我修正了解释(我希望如此)你能解释一下:template void doh::operator()(bool b)中第二个括号后面的原因吗?我认为顶部代码部分中的“template void operator()(int data){”应该是“template void operator()(int data){”,而底部代码部分中的“int g(){”应该是“int g(){”(抱歉,我不知道如何在注释中设置代码部分的样式)我对此有疑问,但GCC和Comeau编译器都认为代码有效。我现在无法测试MSV,如果您能尝试一下,我将不胜感激:)请看我这里的答案。我确实看了,然后回到标准,并用编译器重新测试。如果要为已经有非模板签名的类型专门化模板,则需要额外的一对括号。编译器将在专门化点与两个签名混在一起(将尝试非模板,但无法专门化非模板成员函数)。@James.编译器能够推断出显式专门化的“T”
    #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