C ++:将__file__映射到预定义的数字

时间:2014-01-16 10:25:27

标签: c++ c-preprocessor

这对我来说似乎不可能,但StackOverflow已经解决了以前对我来说似乎不可能的事情,所以在这里:

我在文件名和ID之间有一个预定义的映射,我希望能够在编译时将__FILE__映射到它的id,如果可能的话。

对于粗略的解释感到抱歉,我希望有一个例子可以帮助:

在编译过程开始之前通过某些脚本生成的ID:

#define _FILE_IDS_MAIN_CPP 1
#define _FILE_IDS_HELPER_CPP 2
#define _FILE_IDS_HELPER_HPP 3

在代码中,我希望能够做到这样的事情:

printf("%d", GET_FILEID_MACRO(__file__));

2 个答案:

答案 0 :(得分:0)

为了帮助您入门,您可以使用自C ++ 11以来可用的constexpr函数来对文件名字符执行某些计算。例如,如果您只是让字符串长度为您的ID,则可以:

template <unsigned int N>
constexpr unsigned int FileID(char const (&a)[N])
{
    // your computation goes here
    return N;
}

#include <iostream>
template <unsigned int N> void print()
{
    std::cout << "Static value: " << N << "\n";
}

int main()
{
    print<FileID(__FILE__)>();
}

包含print模板作为编号在编译时计算的证明。

以此作为起点,您可以将FileID更改为某种哈希函数,或者可能更改为静态地图查找 - 这当然是可能的,尽管可能相当冗长。我确定有人已经这样做了。

答案 1 :(得分:0)

拥有C ++ 11:

#include <cstring>
#include <iostream>

constexpr unsigned id(const char* file) {
    return (std::strcmp(file, "One") == 0) ? 1 : 0;
}

template<unsigned>
void print() {
    std::cout << "Zero\n";
}

template<>
void print<1>() {
    std::cout << "One\n";
}

int main () {
    print<id("Zero")>();
    print<id("One")>();
    return 0;
}

不确定strcmp在constexpr函数中是否有效并且在@MSalters链接中的第二个答案之后:

#include <iostream>

// Code from @Robert Mason
// =======================

constexpr bool static_strequal_helper(const char * a, const char * b, unsigned len) {
   return (len == 0) ? true : ((*a == *b) ? static_strequal_helper(a + 1, b + 1, len - 1) : false);
}

template <unsigned N1, unsigned N2>
constexpr bool static_strequal(const char (&str1)[N1], const char (&str2)[N2]) {
   return (N1 == N2) ? static_strequal_helper(&(str1[0]), &(str2[0]), N1) : false;
}

// End


template <unsigned N>
constexpr unsigned id(const char (&file)[N]) {
    return (static_strequal(file, "One")) ? 1 : 0;
}

template<unsigned>
void print() {
    std::cout << "Zero\n";
}

template<>
void print<1>() {
    std::cout << "One\n";
}

int main () {
    print<id("Zero")>();   // Prints Zero
    print<id("One")>();    // Prints One
    print<id(__FILE__)>(); // Prints Zero - Is __FILE__ always an array?
    return 0;
}