c++ - 模板参数替换失败,C 字符串作为非类型模板参数

标签 c++ templates g++ clang++

我正在尝试创建一个允许我做类似事情的类型:

constexpr const char x[] = "x";
constexpr const char y[] = "y";
int main()
{

    Type<_Type<int, x>, _Type<float, y> > truc;
    std::cout << truc.get<std::forward<const char*>(x)>() << std::endl;
}

_Type(将重命名)应该包含从数据库中获取数据(使用模板参数)的代码(成员变量是静态的,因为这样更容易进行测试)。 Type(也将重命名)用于将一堆 _Type 捆绑在一起。

xy 作为局部变量,gcc 表示 x y 没有链接。

类型实现是:

constexpr bool strings_equal(char const* a , char const* b )
{
    return *a == *b && (*a == '\0' || strings_equal(a + 1, b + 1));
}

template <typename T, const char* n>
struct _Type {
    using type = T;
    static constexpr T value = T{};
    static constexpr const char* name = n;
    template <const char* name, typename = typename std::enable_if<strings_equal(n, name)>::value>
    T get()
    {
        return value;
    }
};
template <typename T>
struct _Type2 : T {
};
template <class... T>
struct Type {
    std::tuple<T...> vals;
    template <unsigned idx, const char* name, bool end_ = true>
    auto _get() -> typename decltype(std::get<idx + 1>(vals))::type
    {
        return decltype(std::get<idx + 1>(vals))::value;
    }
    template <unsigned idx, const char* name, bool end_>
    auto _get() -> decltype(
        _get<(idx + 1), std::forward<const char*>(name), strings_equal(name, std::remove_reference<decltype(std::get<idx + 1>(vals))>::type::name)>())
    {
        return _get<idx + 1, std::forward<const char*>(name), string_equal(name, std::remove_reference<decltype(std::get<idx + 1>(vals))>::type::name)>;
    }

    template <const char* name>
    auto get() -> decltype(
        _get<0, std::forward<const char*>(name), strings_equal(name, std::remove_reference<decltype(std::get<0>(vals))>::type::name)>())
    {
        return _get<0, name, string_equal(std::forward<const char*>(name), decltype(std::get<0>(vals))::name)>;
    }
};

此代码产生错误(在编译期间)。

clang 给我这个错误:

test.cpp:60:23: error: no matching member function for call to 'get'
    std::cout << truc.get<std::forward<const char*>(x)>() << std::endl;
                 ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.cpp:48:10: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'name'
    auto get() -> decltype(
         ^
1 error generated.

完整代码和gcc 错误可用here .

我该怎么做才能解决此错误并能够将局部变量用于非类型模板参数

感谢您的回答。

编辑 由于它们的链接,使用本地字符串将不起作用(感谢@PasserBy 的解释)

编辑 2 已解决,感谢@Jarod42

最佳答案

局部变量永远不能有外部链接。曾经。至于为什么链接很重要,请参阅 this .

要点是只有外部链接的 c 字符串在翻译单元之间具有相同的值,然后参数在翻译单元之间才相同。

编译以下代码

constexpr const char x[] = "x";
constexpr const char y[] = "y";

template<typename T, typename U>
struct Type {};

template<typename T, const char*>
struct _Type {};

int main()
{
    //good, external linkage
    Type<_Type<int, x>, _Type<float, y>> t1;

    //won't compile, string literal has internal linkage
    //Type<_Type<int, "x">, _Type<float, "y">> t2;

    static constexpr const char local[] = "x";
    //won't compile, local variables don't have external linkage
    //Type<_Type<int, local>, _Type<float, local>> t3;
}

关于c++ - 模板参数替换失败,C 字符串作为非类型模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43614413/

相关文章:

c++ - typeid 导致不同的编译器

c++ - qsettings 不同的结果

c++ - 什么是 C++ 中的运算符 T*(其中 T 是模板参数)?

loops - 当我将循环放入 Chef 的模板文件中时,出现错误 "TemplateError (no implicit conversion of String into Integer)"

c++ - 为什么 C++ 编译器无法将 "if(test) --foo"优化为 "foo -= test"?

c++ - GNU GCC (g++) : Why does it generate multiple dtors?

c++ - 多个键不起作用

c++ - new[]和delete不匹配,为什么没有内存泄漏?

javascript - 在 JQuery 模板中调用 javascript 函数

c++ - 带有模板的类实例的外部