为什么在类中不允许使用函数模板特化?

时间:2013-09-02 09:29:59

标签: c++ class templates specialization explicit

在找到关于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

如果我把函数执行到类外面,在名称空间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;
    };
};
};

我不能在temp的templatized版本中使用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");
        }
    };
};
};

1 个答案:

答案 0 :(得分:4)

基础专业化:

在.h:

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
}

您将得到:错误:封闭类模板未明确专门化。

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

相关问题