为什么在编译时在g ++中而不是在clang ++中评估此函数

时间:2018-12-24 18:25:10

标签: gcc clang c++17 constexpr

我目前正在寻找一种将类名嵌入到实际对象中的方法。在运行时获取名称不需花任何钱。通过使用以下代码,我在gcc中没有得到任何额外的花费(因为该函数是在编译时评估的),但是由于某种原因,clang不会在编译时评估该代码

我尝试使用不同的编译器版本,但就我测试的所有版本的gcc和所有的clang产生相同的结果而言(我无法真正测试MSVC,因为我找不到它的必要标志)无法产生6K的装配线)

#include <string>
#include <string_view>
#include <iostream>

template<class T>
constexpr std::string_view get_name()
{
    char const* p = __PRETTY_FUNCTION__;
    while (*p++ != '=');
    for (; *p == ' '; ++p);
    char const* p2 = p;
    int count = 1;
    for (;;++p2)
    {
        switch (*p2)
        {
        case '[':
            ++count;
            break;
        case ']':
            --count;
            if (!count)
                return {p, std::size_t(p2 - p)};
        }
    }
    return {};
}

int main(){
    std::string_view s = get_name<std::string>(); 
    std::cout << s << std::endl;
}

C语版本:https://godbolt.org/z/_vY8TD

GCC版本:https://godbolt.org/z/hhXXWi

我希望clang会产生与gcc类似的结果,但事实并非如此

1 个答案:

答案 0 :(得分:0)

重点是get_name()是一个constexpr函数,您已经编写了

 std::string_view s = get_name<std::string>(); 

不是

 constexpr std::string_view s = get_name<std::string>(); 

在第二种情况下(constexpr变量的初始化),编译器必须(几乎:视情况而定)初始化s变量的编译时间。

在您的情况下,执行不依赖于运行时已知值,因此编译器有权选择编译时或运行时执行。

其中一个选择执行编译时,另一个选择执行运行时。

两种行为都是合法的。