什么是为int8_t和uint8_t专门化这个模板函数的更好方法?

时间:2013-04-17 02:38:23

标签: c++ templates template-specialization vmat

考虑下面的模板dump功能:

namespace {

    using namespace Eigen;
    using namespace std;
    using namespace vMAT;

    template <typename T>
    NSString *
    dump(NSString * prefix, T * A, vMAT_Size sizeA)
    {
        NSMutableString * dump = [NSMutableString stringWithString:prefix];
        [dump appendString:@" = \n"];
        Eigen::Map<Matrix<T, Dynamic, Dynamic>> DATA(A, sizeA[0], sizeA[1]);
        stringstream out;
        out << DATA << endl;
        [dump appendFormat:@"%s", out.str().c_str()];
        return dump;
    }

    template <> // Specialized so elements print as numbers instead of chars
    NSString *
    dump(NSString * prefix, int8_t * A, vMAT_Size sizeA)
    {
        NSMutableString * dump = [NSMutableString stringWithString:prefix];
        [dump appendString:@" = \n"];
        Eigen::Map<Matrix<int8_t, Dynamic, Dynamic>> DATA(A, sizeA[0], sizeA[1]);
        stringstream out;
        out << DATA.cast<int32_t>() << endl;
        [dump appendFormat:@"%s", out.str().c_str()];
        return dump;
    }

    template <> // Specialized so elements print as numbers instead of chars
    NSString *
    dump(NSString * prefix, uint8_t * A, vMAT_Size sizeA)
    {
        NSMutableString * dump = [NSMutableString stringWithString:prefix];
        [dump appendString:@" = \n"];
        Eigen::Map<Matrix<uint8_t, Dynamic, Dynamic>> DATA(A, sizeA[0], sizeA[1]);
        stringstream out;
        out << DATA.cast<uint32_t>() << endl;
        [dump appendFormat:@"%s", out.str().c_str()];
        return dump;
    }

}

正如您所看到的,我已复制/粘贴/编辑它以专门化转储int8_tuint8_t矩阵的方式。但这正是模板应该消除的那种疯狂!

我试图在原始函数中添加一个额外的模板typename AsT参数,但是继续与编译器发生冲突抱怨这一行:

out << DATA.cast<AsT>() << endl;

Xcode抱怨cast<AsT>()是一个“依赖模板”,并希望在它前面插入template关键字...这似乎是无意义的语法,然后生成另一个编译器错误。

为int8_t和uint8_t专门化这个模板函数有什么更好的方法?

1 个答案:

答案 0 :(得分:1)

创建另一个功能模板,该模板仅用于uint8_t和/或int8_t,并使您的dump专门化调用其他功能模板。

或者,只需创建从函数模板dump调用的函数的重载。这是一个展示其工作原理的示例:http://ideone.com/Z88DU6

我相信对你的代码这样做会看起来像下面这样,但我并不完全肯定,因为我从未使用过Objective-C(或Objective-C ++)。

// Note: I believe this works but am not a template wizard and have not tried
namespace {

    using namespace Eigen;
    using namespace std;
    using namespace vMAT;

    template <typename T>
    inline Eigen::Map<Matrix<T, Dynamic, Dynamic>> get_printable_eigen(Eigen::Map<Matrix<T, Dynamic, Dynamic>> const& in)
    {
        return in;
    }

    // No specialization; simple overloads!
    inline Eigen::Map<Matrix<int32_t, Dynamic, Dynamic>> get_printable_eigen(Eigen::Map<Matrix<int8_t, Dynamic, Dynamic>> const& in)
    {
        return in.cast<int32_t>();
    }

    inline Eigen::Map<Matrix<uint32_t, Dynamic, Dynamic>> get_printable_eigen(Eigen::Map<Matrix<uint8_t, Dynamic, Dynamic>> const& in)
    {
        return in.cast<uint32_t>();
    }

    template <typename T>
    NSString *
    dump(NSString * prefix, T * A, vMAT_Size sizeA)
    {
        NSMutableString * dump = [NSMutableString stringWithString:prefix];
        [dump appendString:@" = \n"];
        Eigen::Map<Matrix<T, Dynamic, Dynamic>> DATA(A, sizeA[0], sizeA[1]);
        stringstream out;
        out << get_printable_eigen(DATA) << endl;
        [dump appendFormat:@"%s", out.str().c_str()];
        return dump;
    }
}

(可能还有其他解决方案使用enable_if和类型特征,但SFINAE应保留用于无法通过简单方法完成的情况,因为它会产生较差的错误消息)