C++ 模板函数专门化问题

C++ 模板函数专门化问题,c++,enums,C++,Enums,我正在使用模板实现从int到enum的范围检查转换。看起来是这样的: template<typename E> E enum_cast(const int &source); enum ConfigEnum { ConfigEnumOption1 = 'A' , ConfigEnumOption2 = 'B' , ConfigEnumInvalid }; ConfigEnum option = XmlNode.iAttribute("option");

我正在使用模板实现从int到enum的范围检查转换。看起来是这样的:

template<typename E>
E enum_cast(const int &source);
enum ConfigEnum {
    ConfigEnumOption1 = 'A'
  , ConfigEnumOption2 = 'B'
  , ConfigEnumInvalid };

ConfigEnum option = XmlNode.iAttribute("option");
template<typename E>
E enum_cast(const int &source) {
  E copy = source;
  return copy;
};
我在一个.cpp文件中为使用此枚举的模块中的此特定枚举类型定义了一个模板专门化

template<>
ConfigEnum enum_cast(const int &source) {
   switch(source) {
   case ConfigEnumOption1 : return ConfigEnumOption1;
   case ConfigEnumOption2 : return ConfigEnumOption2;
   default return ConfigEnumInvalid;
}
模板
ConfigEnum枚举强制转换(常量int和源){
开关(源){
案例ConfigEnumOption1:返回ConfigEnumOption1;
案例ConfigEnumOption2:返回ConfigEnumOption2;
默认返回值无效;
}
现在,将int赋值给枚举变成:

ConfigEnum option = enum_cast<ConfigEnum>(XmlNode.iAttribute("option"));
ConfigEnum option=enum_cast(XmlNode.iAttribute(“option”);
这确保枚举始终在有效范围内。请注意,我无法始终控制这些枚举,因此这似乎是一个合理且易于配置的解决方案

无论如何,这一切都很好(虽然我不是舒尔,但这里给出的所有代码都是正确的,因为我现在只是从记忆中回忆起来)

问题源于这样一个事实,即可能需要使用此“枚举强制转换”每当一个in被分配给一个枚举时,构造Throughout代码库。毕竟,这可以通过一个简单的搜索和替换操作来实现。当然,我不想为周围的所有和每个枚举定义这些专门化,只想为那些目前需要范围检查的枚举定义这些专门化。我更喜欢为enum在需要时键入,在未定义专门化时使用赋值运算符

因此:

InternalEnum internal=enum\u cast(内部整数);
将有效地调用internal=internal_integer。我想我需要告诉编译器对所有没有专门化的枚举类型使用某种“默认”实现

我的第一个赌注是为原始模板函数提供如下实现:

template<typename E>
E enum_cast(const int &source);
enum ConfigEnum {
    ConfigEnumOption1 = 'A'
  , ConfigEnumOption2 = 'B'
  , ConfigEnumInvalid };

ConfigEnum option = XmlNode.iAttribute("option");
template<typename E>
E enum_cast(const int &source) {
  E copy = source;
  return copy;
};
模板
E enum_cast(常量int和源){
E副本=来源;
返回副本;
};
不幸的是,现在它总是被调用,而不是深入到项目目录树中的.cpp文件中给出的特殊化

有什么想法吗

提前谢谢 阿恩

这个

#include <iostream>

enum e1 { a, b, c, e1_invalid };
enum e2 { x, y, z, e2_invalid };

template<typename E>
E enum_cast(int source)
{
    std::cout << "default implementation\n";
    return static_cast<E>(source);
}

template<>
e2 enum_cast<e2>(int source)
{
    std::cout << "specialization\n";
    switch(source) {
        case x: return x;
        case y: return y;
        case z: return z;
    }
    return e2_invalid;
}

int main(int /*argc*/, char* /*argv*/[])
{
    std::cout << static_cast<int>(enum_cast<e1>(1)) << '\n';
    std::cout << static_cast<int>(enum_cast<e2>(1)) << '\n';
    return 1;
}

显式专门化必须在使用它们的任何地方都可见。由于它们是定义,它们不能在每个编译单元中重复。因此,在定义枚举的头文件中,您要检查

#include "enum_cast.h"
enum Foo { Foo_A, Foo_B, Foo_C };
template<> Foo enum_cast<Foo>(int source);
#包括“enum_cast.h”
枚举Foo{Foo_A,Foo_B,Foo_C};
模板Foo enum_cast(int源代码);

在相应的.cpp中,您给出了定义。

您不能使用traits类来描述每个枚举:

const int LARGE = 65536;

template<typename>
struct EnumTrait
{
    enum {LOW = -LARGE};
    enum {HIGH = LARGE};
};

template<typename ENUM>
static ENUM enum_cast (int i)
{
    if (i < EnumTrait<ENUM>::LOW || i > EnumTrait<ENUM>::HIGH)
        throw std::runtime_error ("Out of bounds");
    return static_cast<ENUM> (i);
}

enum Colour {RED = 0, GREEN, BLUE};

template<>
struct EnumTrait<Colour>
{
    enum {LOW = RED};
    enum {HIGH = BLUE};
};

enum Location {HERE = 0, THERE, NOWHERE};
// No EnumTraits class.

int main (int argc, char* argv[])
{
    int i = 2;

    Colour c = enum_cast<Colour> (i);
    std::cout << "c=" << c << std::endl;

    Location l = enum_cast<Location> (i);
    std::cout << "l=" << l << std::endl;

    return 0;
}
const int LARGE=65536;
模板
结构枚举特征
{
枚举{LOW=-LARGE};
枚举{高=大};
};
模板
静态枚举枚举强制转换(int i)
{
if(iEnumTrait::HIGH)
抛出std::runtime_错误(“越界”);
返回静态_-cast(i);
}
枚举颜色{红色=0,绿色,蓝色};
模板
结构枚举特征
{
枚举{LOW=RED};
枚举{HIGH=BLUE};
};
枚举位置{HERE=0,THERE,NOWHERE};
//没有枚举类。
int main(int argc,char*argv[])
{
int i=2;
颜色c=枚举(i);

STD:可能是因为所有的专业都位于同一个文件中。在我的例子中,EnUM定义和特殊化通常是在不同的文件中。我猜想AProgrammer的评论会纠正我的问题,感谢这个提示——像往常一样,一旦你知道答案,就很容易了。-我会考虑这个方法来解决未来的项目。但是现在我需要赶在最后期限之前…非常感谢!