为什么类中不允许函数模板专业化

Why are function template specializations not allowed inside a class?

本文关键字:函数模板 专业化 不允许 为什么      更新时间:2023-10-16

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

我的问题是,我想在C++中对类内的函数进行显式模板化。我的编译器(g++)和C++标准(§14.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");
    }
};

这是不可能的;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

如果我把函数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;
    };
};
};

并且我不能在execute的模板化版本中使用privatevariable,因为它在类中是私有的。我真的很想它是私有的,因为我想尽可能地封装我的数据。

当然,我可以将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");
        }
    };
};
};

基础专业化:

英寸:

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

在相同名称空间下的.cpp中:

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

如果你想在专业类中使用专业功能:

内部类添加(.h)(私有函数):

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

cpp:内部的专业化

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

更新:

但你不能写这样的东西:

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

您将得到:error:封闭类模板不是显式专用的。

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