如果使用某种特殊化,则编译失败

时间:2012-03-06 20:37:25

标签: c++ templates

是否可以以这种方式对模板进行特化处理,以便在实例化该特化时导致编译错误?例如,我有一个类int作为一个类型没有意义的类:

class Careful
{
    template <typename T>
    void f(T value) { std::cout << "Non-specialized version"; }
};

template <>
void Careful::f(double value)
{
    std::cout << "specialization for double";
}

template <>
void Careful::f(int value)
{
    // make this one fail to compile
}

这种方式是否可行(理想情况下是一条有意义的错误信息)?

4 个答案:

答案 0 :(得分:4)

如果您想要自定义错误消息,并且可以使用C ++ 11,则可以使用新的static_assert

class Careful
{    
    template <typename T>
    void f(T value) {
        static_assert(std::is_same<T, int>::value, "Don't call f with an int!");
    }
};

修改

我以为我可以解释一件事。当然,可以通过static_assertenable_if或不定义函数(这些是已给出的三个答案)为给定的特化引起错误消息。但我不知道某种方法强制给定特殊化的错误。

static_assertenable_if技术受SFINAE约束,因此如果有人稍后将此功能添加到Careful类,您将不会收到错误:

void f(int value)
{
    std::cout << "Overloaded!" << std::endl;
}

(我认为这是一件好事,但仍然值得注意)。同样,代码template<> void Careful::f(int value);只是f专业化的前向声明 - 之后,有人可以为它添加定义。

编辑2

是的,这个问题看起来得到了解答,但我认为我应该采用最直接的方法(以及IMO,“正确的”方法):使用delete

class Careful
{
    template <typename T>
    void f(T value) { std::cout << "Non-specialized version"; }
};

template <>
void Careful::f(double value)
{
    std::cout << "specialization for double";
}

template <>
void Careful::f(int value) = delete;

delete有点像@hmjd没有定义函数的方法,但显式表示没有人可以提供函数的实现。此外,编译器消息将是描述性的(请注意,它是编译器错误,而不是链接器错误,因此可能更容易找到错误的来源)。在g ++上,使用delete d函数的错误消息读取error: use of deleted function ‘void Careful::f(T) [with T = int]’。如果有人后来试图在其他地方定义该函数,他们最终会得到错误redefinition of ‘void Careful::f(T) [with T = int]’而不是没有错误。

答案 1 :(得分:3)

当模板专用于特定类型时,您可以使用boost::enable_if生成编译时错误

答案 2 :(得分:2)

声明专业化但不提供定义会导致失败:

template <>
void Careful::f(int value);

答案 3 :(得分:1)

您至少可以使链接失败。只是不要为类型实现函数,这是没有意义的:

#include <iostream>
using namespace std;

class Careful
{
public:
    template <typename T>
    void f(T value) { std::cout << "Non-specialized version"; }
};

template <>
void Careful::f(double value)
{
    std::cout << "specialization for double";
}

template <>
void Careful::f(int value); // int makes no sense. As long as you don't implement it for this type, compilation will fail at instantiation.

int main() {
    Careful x;
    x.f(3.14);
    x.f(42); // this will fail
}

使用我的g ++,我在链接步骤中收到此错误:

 main.cpp:(.text+0x4b): undefined reference to `void Careful::f<int>(int)'

这不是自定义消息,但链接失败。