C++ 为什么类中不允许函数模板专门化?

C++ 为什么类中不允许函数模板专门化?,c++,class,templates,specialization,explicit,C++,Class,Templates,Specialization,Explicit,在找到stackoverflow上许多问题的答案后,我现在遇到了一个我找不到答案的问题,我希望有人愿意帮助我 我的问题是,我想在C++中的一个类中对函数进行显式的模板化。我的编译器(G++)和C++标准中的一个视图(专利文献7.7.3)告诉我,这个特殊化必须在声明类的命名空间中完成。我明白这意味着我不能将专门化放在类中,但我不明白这种限制的意义!有人知道有没有一个很好的理由不让专业化在课堂上进行吗 我知道有一些变通方法,例如将函数放在结构中,但我想了解为什么语言有这种设计。如果有一个很好的理由不

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

我的问题是,我想在C++中的一个类中对函数进行显式的模板化。我的编译器(G++)和C++标准中的一个视图(专利文献7.7.3)告诉我,这个特殊化必须在声明类的命名空间中完成。我明白这意味着我不能将专门化放在类中,但我不明白这种限制的意义!有人知道有没有一个很好的理由不让专业化在课堂上进行吗

我知道有一些变通方法,例如将函数放在结构中,但我想了解为什么语言有这种设计。如果有一个很好的理由不允许在类中使用专门的函数,我想我应该在尝试解决它之前知道它

提前谢谢


让我的问题更精确一点:下面是一个测试示例中的一些代码,它说明了我要做的事情:

#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");
    }

};
#包括
命名空间恶意程序{
模板
类专门化测试{
公众:
专门化测试(){
私有变量=5;
};
virtual~SpecializationTest(){};
void execute(){
执行();
};
私人:
int私有变量;
模板
静态void execute(){
printf(“这是一般情况。当前dim为%d。专用变量为%d。\n”,currentDim,privateVariable);
执行();
}
模板
静态void execute(){
printf(“这是基本情况。当前dim为0。\n”);
}
};
这是不可能的;g++说:

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
SpecializationTest\u fcn.h:27:错误:在非命名空间范围“class MalinTester::SpecializationTest”中显式专门化
SpecializationTest\u fcn.h:28:错误:主模板声明中的模板id“execute”
如果我将函数execute放在类之外的名称空间MalinTester中,它将如下所示:

#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;
    };
};
};
template <class T>
template <>
void UISelectorSlider<T>::foo<3>()
{
     // you can access private fields here
}
#包括
命名空间恶意程序{
模板类SpecializationTest{};
模板
void execute(){
printf(“这是一般情况。当前dim为%d。专用变量为%d。\n”,currentDim,privateVariable);
执行();
}
模板
void execute(){
printf(“这是基本情况。当前dim为0。\n”);
}
模板
类专门化测试{
公众:
SpecializationTest(){};
virtual~SpecializationTest(){};
void execute(){
MalinTester::execute();
};
私人:
int privatevaluate=5;
};
};
};
我不能在模板化版本的execute中使用privatevariable,因为它在类中是私有的。我真的希望它是私有的,因为我希望尽可能地封装我的数据

当然,我可以将私有的作为参数发送给函数,但是我认为避免这种情况会更漂亮,我真的很想知道,C++的标准是否有一个很好的理由,不允许在上面的第一个代码示例中允许显式的专门化。
@Arne Mertz:这是我尝试过的解决方法,但它也不允许使用privateVariable。最重要的是,我想知道这样做是否是个好主意。由于我不允许对成员函数进行专门化,也许我也不应该对封装在类内部结构中的函数进行专门化

#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");
        }
    };
};
};
#包括
命名空间恶意程序{
模板
类专门化测试{
公众:
专门化测试(){
私有变量=5;
};
virtual~SpecializationTest(){};
void execute(){
循环::执行();
};
私人:
int私有变量;
模板
结构循环{
静态void execute(){
printf(“这是一般情况。当前dim为%d。\n”,currentDim);
循环::执行();
}
};
模板
结构循环{
静态void execute(){
printf(“这是基本情况。当前dim为0。\n”);
}
};
};
};
基本专业化:

在h中:

template <class T>
class UISelectorSlider :  public UISelectorFromRange<T> {
public:
    UISelectorSlider();
    virtual ~UISelectorSlider();
private:
    float width;
    float getPositionFromValue(T value);
};
模板
类UISelectorSlider:公共UISelectorFromRange{
公众:
UISelectorSlider();
虚拟~UISelectorSlider();
私人:
浮动宽度;
浮点getPositionFromValue(T值);
};
在同一命名空间下的.cpp中:

template <>
float UISelectorSlider<MVHue>::getPositionFromValue(MVHue value)
{
    return width * (float)value / 360.0;
}
模板
浮点UISelectorSlider::getPositionFromValue(MVHue值)
{
返回宽度*(浮动)值/360.0;
}
如果要在专用类中使用专用函数:

类内添加(.h)(专用函数):

private:
模板
void foo();
.cpp内的专门化:

template <>
template <>
void UISelectorSlider<MVHue>::foo<3>()
{
     // you can access private fields here
}
模板
模板
void UISelectorSlider::foo()
{
//您可以在这里访问私有字段
}
更新:

但你不能写这样的东西:

#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;
    };
};
};
template <class T>
template <>
void UISelectorSlider<T>::foo<3>()
{
     // you can access private fields here
}
模板
模板
void UISelectorSlider::foo()
{
//您可以在这里访问私有字段
}
您将得到:错误:封闭类模板未显式专用化

这个定义是在类中还是在命名空间中并不重要。关键是,这不是精确的部分专门化-此函数没有定义上下文类(您要调用的成员)。换句话说,当您专门化成员时,您实际上尝试专门化整个包含类,而不是成员本身。编译器不能这样做,因为类尚未完全定义。这就是模板设计的限制。如果它真的起作用,模板将完全等同于简单的宏。
(你可能会用一些宏魔法来解决你的任务。)

我认为这是相关的。到底有什么问题需要解决?你不能把专门化放在名称空间里吗?n.m.:我想要