为什么在类中不允许函数模板特殊化? [英] Why are function template specializations not allowed inside a class?

查看:159
本文介绍了为什么在类中不允许函数模板特殊化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在找到我对stackoverflow的许多问题的答案后,我现在提出了一个问题,我找不到答案,我希望有人愿意帮助我!



我的问题是,我想在C ++中的类中做一个函数的显式模板化。我的编译器(g ++)和C ++标准(§14.7.3)告诉我,这个专门化必须在声明类的命名空间中完成。我明白这意味着我不能把专业化在类中,但我没有看到这个限制的点!有没有人知道是否有一个很好的理由不让专业化在课堂内?



我知道有解决方法,例如。把函数放在一个结构体中,但是我想了解为什么语言有这个设计。如果有一个很好的理由不允许在类中的专门的功能,我想我应该知道它,然后尝试解决它。​​



提前感谢!






为了使我的问题更精确一点:下面是一个测试示例中的一些代码,说明我想做什么: / p>

  #include< cstdio> 

命名空间MalinTester {

模板< size_t DIMENSIONALITY>
class specializationTest {
public:
SpecializationTest(){
privateVariable = 5;
};
virtual〜SpecializationTest(){};

void execute(){
execute< DIMENSIONALITY>();
};

private:
int privateVariable;
template< size_t currentDim>
static void execute(){
printf(这是一般情况下,当前dim是%d。私有变量是%d.\\\
,currentDim,privateVariable);
execute< currentDim-1>();
}

模板<>
static void execute< 0>(){
printf(This is the base case。Current dim is 0. \\\
);
}

};

这是不可能的; g ++说:

  SpecializationTest_fcn.h:27:错误:非命名空间范围中的显式专门化'class MalinTester :: SpecializationTest< DIMENSIONALITY> ;'
SpecializationTest_fcn.h:28:error:template-id'在主模板声明中执行< 0>'

如果我把函数在类外面执行,在命名空间MalinTester中,它将看起来像这样:

  #include< cstdio> 

命名空间MalinTester {

模板< size_t DIMENSIONALITY> class SpecializationTest {};

template< size_t currentDim>
void execute(){
printf(这是一般情况下,当前dim为%d。私有变量为%d.\\\
,currentDim,privateVariable);
execute< currentDim-1>();
}

模板<>
void execute< 0>(){
printf(This is the base case。Current dim is 0. \\\
);
}

模板< size_t DIMENSIONALITY>
class SpecializationTest {
public:
SpecializationTest(){};
virtual〜SpecializationTest(){};

void execute(){
MalinTester :: execute< DIMENSIONALITY>();
};
private:
int privateVariable = 5;
};
};
};

我不能在模板化版本的execute中使用privatevariable,因为它是类中的私有。



当然,我可以将privateVariable作为参数发送到函数,但我认为避免这将是更美丽的,我真正想知道的是,如果有一个很好的理由C ++标准不允许显式专门化,如上面的第一个代码示例。






@Arne Mertz:这是我试过的解决方法,但它不允许使用privateVariable。最重要的是,我想知道这样做是否是个好主意。因为我不允许成员函数的专门化,也许我不应该在类中的structs封装的函数的专业化。

  #include< cstdio> 

命名空间MalinTester {

模板< size_t DIMENSIONALITY>
class SpecializationTest {
public:
SpecializationTest(){
privateVariable = 5;
};
virtual〜SpecializationTest(){};

void execute(){
Loop< DIMENSIONALITY,0> :: execute()
};

private:
int privateVariable;

template< size_t currentDim,size_t DUMMY>
struct Loop {
static void execute(){
printf(这是一般情况下,当前昏暗的是%d.\\\
,currentDim);
Loop< currentDim-1,0> :: execute();
}
};

模板< size_t DUMMY>
struct Loop< 0,DUMMY> {
static void execute(){
printf(This is the base case。Current dim is 0. \\\
);
}
};
};
};


解决方案

基本专业化:



在.h中:

 模板< class T& 
class UISelectorSlider:public UISelectorFromRange< T> {
public:
UISelectorSlider();
virtual〜UISelectorSlider();
private:
float width;
float getPositionFromValue(T value);
};

在同一命名空间下的.cpp中:

 模板<> 
float UISelectorSlider< MVHue> :: getPositionFromValue(MVHue value)
{
return width *(float)value / 360.0;
}

如果你想在专门的类中使用专门的函数:



在类中添加(.h)(私有函数):

  private:
template< int I>
void foo();

.cpp中的专业化:

  template<> 
模板<>
void UISelectorSlider< MVHue> :: foo< 3>()
{
//可以访问此处的私有字段
}



更新:



但你不能这样写:

 模板< class T> 
模板<>
void UISelectorSlider< T> :: foo< 3>()
{
//可以访问此处的私有字段
}



您会得到:error:封闭类模板没有明确专用。



事物是类或命名空间中的这个定义。关键是这不是精确的部分专业化 - 这个函数没有定义的上下文类(你想调用的成员)。换句话说 - 当你专门化成员,你实际尝试专门化整个包含类,但不是成员本身。编译器不能这样做,因为类还没有完全定义。所以这是通过模板设计的限制。如果它实际工作 - 模板将完全等同于简单的宏。
(你可能会用一些宏魔法来解决你的任务。)


After having found answers to many of my questions on stackoverflow, I have now come up against a question of which I can't find the answer and I hope that someone is willing to help me!

My problem is that I want to do an explicit templatization of a function inside a class in C++. My compiler (g++) and a look in the C++ standard (§14.7.3) tells me that this specialization has to be done in the namespace in which the class is declared. I understand that this implies that I cannot put the specialization inside the class, but I don't see the point of this restriction! Does anyone know if there is a good reason for not letting the specializations be made inside the class?

I know that there are workarounds, e.g. to put the function inside a struct, but I want to understand why the language has this design. If there is a good reason for not allowing specialized functions inside the class, I guess I should know it before trying to work around it.

Thanks in advance!


To make my question a little bit more precise: Here is some code from a test example which illustrates what I want to do:

#include <cstdio>

namespace MalinTester {

template <size_t DIMENSIONALITY>
class SpecializationTest {
public:
    SpecializationTest() {
        privateVariable = 5;
    };
    virtual ~SpecializationTest() {};

    void execute() {
        execute<DIMENSIONALITY>();
    };

private:
    int privateVariable;
    template <size_t currentDim>
    static void execute() {
        printf("This is the general case. Current dim is %d. The private variable is %d.\n", currentDim, privateVariable);
        execute<currentDim-1>();
    }

    template <>
    static void execute<0>() {
        printf("This is the base case. Current dim is 0.\n");
    }

};

This is not possible; g++ says:

SpecializationTest_fcn.h:27: error: explicit specialization in non-namespace scope ‘class MalinTester::SpecializationTest<DIMENSIONALITY>’
SpecializationTest_fcn.h:28: error: template-id ‘execute<0>’ in declaration of primary template

If I put the function execute outside the class, in the name space MalinTester, it will look like this:

#include <cstdio>

namespace MalinTester {

    template <size_t DIMENSIONALITY> class SpecializationTest {};

    template <size_t currentDim>
    void execute() {
        printf("This is the general case. Current dim is %d. The private variable is %d.\n", currentDim, privateVariable);
        execute<currentDim-1>();
    }

    template <>
    void execute<0>() {
        printf("This is the base case. Current dim is 0.\n");
    }

    template <size_t DIMENSIONALITY>
    class SpecializationTest {
    public:
        SpecializationTest() {};
        virtual ~SpecializationTest() {};

        void execute() {
            MalinTester::execute<DIMENSIONALITY>();
        };
    private:
        int privateVariable = 5;
    };
};
};

and I cannot use privatevariable in the templatized versions of execute, as it is private in the class. I really want it private, as I want to have my data encapsulated as far as possible.

Of course I can send privateVariable as an argument to the function, but I think it would be more beautiful to avoid this, and what I really wonder is if there is a good reason for the C++ standard not to allow explicit specialization as in the first code example above.


@Arne Mertz: This is the workaround I have tried, but it doesn't allow using privateVariable either. And most of all, I wonder if it is a good idea to do like this. As I'm not allowed to make specializations of member functions, maybe I shouldn't do specializations of functions encapsulated in structs inside the class either.

#include <cstdio>

namespace MalinTester {

template <size_t DIMENSIONALITY>
class SpecializationTest {
public:
    SpecializationTest() {
        privateVariable = 5;
    };
    virtual ~SpecializationTest() {};

    void execute() {
        Loop<DIMENSIONALITY, 0>::execute();
    };

private:
    int privateVariable;

    template <size_t currentDim, size_t DUMMY>
    struct Loop {
        static void execute() {
            printf("This is the general case. Current dim is %d.\n", currentDim);
            Loop<currentDim-1, 0>::execute();
        }
    };

    template <size_t DUMMY>
    struct Loop<0, DUMMY> {
        static void execute() {
            printf("This is the base case. Current dim is 0.\n");
        }
    };
};
};

解决方案

Base specialization:

In .h:

template <class T>
class UISelectorSlider :  public UISelectorFromRange<T> {
public:
    UISelectorSlider();
    virtual ~UISelectorSlider();
private:
    float width;
    float getPositionFromValue(T value);
};

In .cpp under same namespace:

template <>
float UISelectorSlider<MVHue>::getPositionFromValue(MVHue value)
{
    return width * (float)value / 360.0;
}

If you want specialized function within specialized class:

Inside class add (.h) (private function):

private:
    template <int I>
    void foo();

Specialization inside .cpp:

template <>
template <>
void UISelectorSlider<MVHue>::foo<3>()
{
     // you can access private fields here
}

UPDATE:

But you cant write something like this:

template <class T>
template <>
void UISelectorSlider<T>::foo<3>()
{
     // you can access private fields here
}

You will get: error: enclosing class templates are not explicitly specialized.

It does not matter is this definition inside class or in namespace. The point is that this is not exact partial specialization - this function does not have defined context class (which members you want to call). In other words - when you specialize member you actually try specialize the whole containing class, but not the member itself. And compiler cant do that because class is not yet defined completely. So this is restriction by template design. And if it actually worked - templates would be full equivalent to simple macros. (And you probably can will solve your task with some macro magic.)

这篇关于为什么在类中不允许函数模板特殊化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆