How to extract the source filename without path and suffix at compile time?

后端 未结 4 2075
南旧
南旧 2020-11-30 00:51

Using both gcc with -std=c11 and g++ with -std=c++14.

E.g. for a file named src/dir/Hello.cxx it should expand to something like e.g.:

c         


        
4条回答
  •  猫巷女王i
    2020-11-30 01:22

    extract the base filename at compile time with no preprocessor tricks and no external scripts? c++14? no problem sir.

    #include 
    #include 
    
    using namespace std;
    
    namespace detail {
        constexpr bool is_path_sep(char c) {
            return c == '/' || c == '\\';
        }
    
        constexpr const char* strip_path(const char* path)
        {
            auto lastname = path;
            for (auto p = path ; *p ; ++p) {
                if (is_path_sep(*p) && *(p+1)) lastname = p+1;
            }
            return lastname;
        }
    
        struct basename_impl
        {
            constexpr basename_impl(const char* begin, const char* end)
            : _begin(begin), _end(end)
            {}
    
            void write(std::ostream& os) const {
                os.write(_begin, _end - _begin);
            }
    
            std::string as_string() const {
                return std::string(_begin, _end);
            }
    
            const char* const _begin;
            const char* const _end;
        };
    
        inline std::ostream& operator<<(std::ostream& os, const basename_impl& bi) {
            bi.write(os);
            return os;
        }
    
        inline std::string to_string(const basename_impl& bi) {
            return bi.as_string();
        }
    
        constexpr const char* last_dot_of(const char* p) {
            const char* last_dot = nullptr;
            for ( ; *p ; ++p) {
                if (*p == '.')
                    last_dot = p;
            }
            return last_dot ? last_dot : p;
        }
    }
    
    // the filename with extension but no path
    constexpr auto filename = detail::strip_path(__FILE__);
    constexpr auto basename = detail::basename_impl(filename, detail::last_dot_of(filename));
    
    auto main() -> int
    {
        cout << filename << endl;
        cout << basename << endl;
    
        cout << to_string(basename) << endl;
    
        return 0;
    }
    

提交回复
热议问题