简体   繁体   English

功能模板重载-部分专业化

[英]Function template overloading - partial specialization

I have 2 classes that follow a similar pattern: 我有两个遵循类似模式的类:

Foo.h oo

// header guard here 

class Foo {
public:
    Foo() = delete;

    static foo1& getFoo1( Param a, Param b, Param c ) {
        // code...
    }

    static foo2& getFoo2( Param a, Param b, Param c ) {
        // code...
    }

    // generic function to return appropriate Foo Type based on template argument 
    template<class FooType>
    static FooType& getFoo( Param a, Param b, Param c );
};

#endif

Foo.cpp Foo.cpp

#include <Foo.h>

// specializations of getFoo() for each type
template<>
foo1& Foo::getFoo( Param a, Param b, Param c ) {
    return getFoo1( a, b, c );
}

template<>
foo2& Foo::getFoo( Param a, Param b, Param c ) {
    return getFoo2( a, b, c );
}

Foo above compiles just fine. 上面的Foo编译就好了。 Bar on the other hand has a similar structure or pattern as Foo above; 另一方面, Bar具有与上面的Foo类似的结构或样式; the only difference is that it's static getBar1() , getBar2() etc. are not just normal functions; 唯一的区别是它是静态的getBar1()getBar2()等不只是普通的函数; they are function templates. 它们是功能模板。

Bar.h Bar.h

// header guard

class Bar {
public:
    Bar() = delete;

    template<class IntType = int>
    static bar1<IntType>& getBar1( IntType a, IntType b ) {
        // code...
    }

    template<class RealType = double>
    static bar2<RealType>& getBar2( RealType a, RealType b ) {
        // code...
    }

    template<class IntType = int>
    static bar3<IntType>& getBar3( IntType a ) {
        // code...
    }

    template<class RealType = double>
    static bar4<RealType>& getBar4( RealType a ) {
        // code...
    }

    // ...

    template<class RealType = double>
    static bar12<RealType>& getBar12() {
        // code...
    }

    template<class RealType = double, class A, class B>
    static bar12&<RealType>& getBar12( A a1, A a2, B b1 ) {
        // code...
    }

    template<class RealType = double, class X>
    static bar12&<RealType>& getBar12( std::initialize_list<double> list, X x ) {
        // code...
    }

    template<class RealType = double, class X>
    static bar12&<RealType>& getBar12( std::size_t size, RealType a, RealType b, X x ) {
        // code..
    }

    // Here is where I start to get into problems:
    // I'm trying to do something similar to what I've done above in Foo for a generic function template.
    template<typename Type, template<typename> class BarType, class... FuncParams>
    static BarType<Type>& getBar( FuncParams... params );

}; 

#endif

Bar.cpp Bar.cpp

#include "Bar.h"

// specializations of getBar() for each type
template<typename Type, class... FuncParams>
bar1<Type>& Bar::getBar( FuncParams... params ) {
    return getBar1( params... );
}

template<typename Type, class... FuncParms>
bar2<Type>& Bar::getBar( FuncParams... params ) {
    return getBar2( params... );
}

Why is it that when I begin to added a class type that is a class template; 为什么当我开始添加作为类模板的类类型时为什么? everything seems to break. 一切似乎都坏了。 The first class above compiles and returns back the appropriate Foo . 上面的第一个类编译并返回适当的Foo However, in the second class Bar I keep getting compiler errors that function definition is not matching an existing declaration. 但是,在第二个类Bar我不断收到函数定义与现有声明不匹配的编译器错误。

This question is related to this one here: Specializing and or Overloading member function templates with variadic parameters 这个问题与这里的问题有关: 使用可变参数参数化和/或重载成员函数模板

This question is specifically about why the one does compile and the other one doesn't. 这个问题专门针对为何一个人编译而另一个人不编译的问题。

The first class above compiles and returns back the appropriate Foo 上面的第一个类编译并返回适当的Foo

Yes, because 是的,因为

template<>
foo1& Foo::getFoo( Param a, Param b, Param c ) {
    return getFoo1( a, b, c );
}

it's a full specialization of the template method getFoo() 这是模板方法getFoo()完全专业化

template<class FooType>
static FooType& getFoo( Param a, Param b, Param c );

with the FooType type fixed to foo1 . FooType类型固定为foo1

And you can make a full specialization of a template function (or method). 您可以对模板功能(或方法)进行完全专业化。

However, in the second class Bar I keep getting compiler errors that function definition is not matching an existing declaration. 但是,在第二个类Bar我不断收到函数定义与现有声明不匹配的编译器错误。

Sure. 当然。

Because you're trying to partial specialize the template method getBar() 因为您正在尝试部分专门化模板方法getBar()

template<typename Type, template<typename> class BarType, class... FuncParams>
static BarType<Type>& getBar( FuncParams... params );

fixing BarType to bar1 BarType固定到bar1

template<typename Type, class... FuncParams>
bar1<Type>& Bar::getBar( FuncParams... params ) {
    return {};//getBar1( params... );
}

But you can't partial specialize a template function/method. 但是您不能部分专门化模板功能/方法。 It's forbidden by the language. 该语言禁止使用。

If you want something similar, you have to pass through the partial specialization of a struct (or class). 如果您想要类似的东西,则必须通过结构(或类)的部分专业化。

--- EDIT --- -编辑-

The OP ask OP问

You said, "you have to pass through the partial specialization of a struct( or class)." 您说过:“您必须经历struct(或类)的部分专业化。” Okay; 好的; so there is a work around: would you be able to provide a small basic example? 因此,有一个解决方法:您能否提供一个小的基本示例?

There are many ways to use partial specialization of structs (classes) to bypass the non-partial-specialization limits for functions/methods. 有很多方法可以使用结构(类)的部分专业化来绕过函数/方法的非部分专业化限制。

In the following basic example I propose a template foo struct with a template func() method. 在下面的基本示例中,我提出了带有模板func()方法的模板foo结构。 The single template parameter for foo is the type returned by func() ; foo的单个模板参数是func()返回的类型; the variadic template type list for func() is the list of types of arguments. func()的可变参数模板类型列表是参数类型的列表。

But you can play this game in differents modes. 但是您可以以不同模式玩此游戏。

#include <iostream>

template <typename>
struct bar1
 { template <typename ... Args> bar1 (Args && ...) { } };

template <typename>
struct bar2
 { template <typename ... Args> bar2 (Args && ...) { } };

template <typename>
struct foo;

template <typename T>
struct foo<bar1<T>>
 {
   template <typename ... Args>
   static bar1<T> func (Args && ... as)
    { return { std::forward<Args>(as)... }; }
 };

template <typename T>
struct foo<bar2<T>>
 {
   template <typename ... Args>
   static bar2<T> func (Args && ... as)
    { return { std::forward<Args>(as)... }; }
 };

int main()
 {
   foo<bar1<int>>::func(1, "two", 3.0);
   foo<bar2<long>>::func(4.0f, "five", 6L);
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM