【问题标题】:How to define a contructor for <...auto...>如何为 <...auto...> 定义构造函数
【发布时间】:2020-11-16 00:04:06
【问题描述】:

使用以下程序(它是我正在试验的较大程序的摘录),我收到一条错误消息,似乎与 fixed_string 的构造函数有关

#include <string>
#include <cstring>

template<std::size_t N>
struct fixed_string {
    static const constexpr std::size_t size__ = N;

    constexpr fixed_string(char const* s) :
            buf("") {
        for (std::size_t i = 0; i <= N; ++i)
            buf[i] = s[i];
    }
    constexpr operator char const*() const {
        return buf;
    }
    constexpr bool operator==(const char* other) const {
        return ::strncmp(buf, other, N) == 0;
    }
    template<std::size_t M>
    constexpr bool compare(const fixed_string<M>& other) const {
        return (N == M && ::strncmp(buf, other.buf, N) == 0) ? std::true_type(): std::false_type();
    }

    char buf[N + 1];
};

template<std::size_t N>
fixed_string(char const (&)[N]) -> fixed_string<N - 1>;

////////////////////////////////////////////

template<fixed_string TARGET_NAME, fixed_string THIS_NAME>
concept NameMatches = (TARGET_NAME.compare(THIS_NAME));

template<fixed_string NAME, typename TYPE>
class Member {
public:
    static const constexpr fixed_string name__ { NAME };

public:
    template<fixed_string TARGET_NAME>
    const TYPE& get() const requires NameMatches<TARGET_NAME, TYPE::name__> const {
        return member_;
    }

protected:
    TYPE member_;
};

template<typename ... MEMBERS>
class Container: public MEMBERS... {
};

错误信息是:

../src/test-concepts.cpp:43:35: error: class template argument deduction failed:
   43 |  const TYPE& get() const requires NameMatches<TARGET_NAME, TYPE::name__> const {
      |                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/test-concepts.cpp:43:35: error: no matching function for call to ‘fixed_string(fixed_string<...auto...>)’
../src/test-concepts.cpp:8:12: note: candidate: ‘template<long unsigned int N> fixed_string(const char*)-> fixed_string<N>’
    8 |  constexpr fixed_string(char const* s) :
      |            ^~~~~~~~~~~~
../src/test-concepts.cpp:8:12: note:   template argument deduction/substitution failed:
../src/test-concepts.cpp:43:35: note:   couldn’t deduce template parameter ‘N’
   43 |  const TYPE& get() const requires NameMatches<TARGET_NAME, TYPE::name__> const {
      |                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/test-concepts.cpp:5:8: note: candidate: ‘template<long unsigned int N> fixed_string(fixed_string<N>)-> fixed_string<N>’
    5 | struct fixed_string {
      |        ^~~~~~~~~~~~
../src/test-concepts.cpp:5:8: note:   template argument deduction/substitution failed:
../src/test-concepts.cpp:43:35: note:   mismatched types ‘fixed_string<N>’ and ‘fixed_string<...auto...>’
   43 |  const TYPE& get() const requires NameMatches<TARGET_NAME, TYPE::name__> const {
      |                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/test-concepts.cpp:28:1: note: candidate: ‘template<long unsigned int N> fixed_string(const char (&)[N])-> fixed_string<(N - 1)>’
   28 | fixed_string(char const (&)[N]) -> fixed_string<N - 1>;
      | ^~~~~~~~~~~~
../src/test-concepts.cpp:28:1: note:   template argument deduction/substitution failed:
../src/test-concepts.cpp:43:35: note:   mismatched types ‘const char [N]’ and ‘fixed_string<...auto...>’
   43 |  const TYPE& get() const requires NameMatches<TARGET_NAME, TYPE::name__> const {
      |                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/test-concepts.cpp:43: confused by earlier errors, bailing out

这是使用模板的项目的一部分,该模板重载给定函数(在本例中为get),对于该模板,只有一个满足约束的合适候选者。约束操作的值是名称 - 字符串文字 - 不是 const 字符串变量,它作为非类型参数传递给模板的实例化:类似于:

Container<Member<"fred", std::string>, Member<"bert", int>, Member<"alfie", bool>> some_values;

我希望能够使用类似的东西检索一个值

int result = some_values.get<"bert">();

我很难找到有关模板的“&lt;...auto...&gt;”专业化的大量信息。我认为这是gcc 用于常量、非类型值的内部表示。

错误消息指出我缺少适合fixed_string 的重载构造函数。这应该是什么?

【问题讨论】:

  • 无关:operator==(const char*)compare 似乎不一致。为什么N == Mcompare 中必须是true?现在可以static_cast&lt;const char*&gt;(the_rhs_fixed_string) 并使用operator==(const char*) 并获得true 其中compare 将返回false
  • Compare 仅用于一个特定目的:确保两个字符串在约束的上下文中绝对相同。但是你的评论很好 - 我会玩它。

标签: c++ templates c++20 c++-concepts


【解决方案1】:

我看到的问题是fixed_string 是一个模板 类,而不是一个类。

所以,当你定义一个概念时

template<fixed_string TARGET_NAME, fixed_string THIS_NAME>
concept NameMatches = (TARGET_NAME.compare(THIS_NAME));

您认为fixed_string TARGET_NAME(也有fixed_string THIS_NAME)不起作用,因为fixed_string 不是一种类型。我的意思是:fixed_string&lt;5&gt; 是一种类型,而不是 fixed_string

我知道你有一个推导指南,给定文字字符串,推导出 fixed_string 的模板参数,但仍然存在这个概念应该适用于不同类型元素的问题(不同长度的fixed_string) .

我想你可以用auto解决问题

template <auto TARGET_NAME, auto THIS_NAME>
concept NameMatches = (TARGET_NAME.compare(THIS_NAME));

但是,当您声明 Member 时,您会遇到同样的问题:fixed_string NAME 不起作用,因为 fixed_sting(没有长度)不是类型。

template<fixed_string NAME, typename TYPE>
class Member

很遗憾,如果你使用auto

template <auto NAME, typename TYPE>
class Member

使用文字字符串参数(例如Member&lt;"bert", int&gt;)定义Member,不会将"bert" 带到fixed_string

建议:没有模板参数的fixed_string 怎么样?

【讨论】:

  • 这是一个可爱、有用的答案。奇怪的是,GCC 似乎很高兴没有为 fixed_string 指定参数 N。我想知道我是否在编译器中发现了一个漏洞,因为当我使用简单的 char* 初始化一个 fixed_string 时,CLANG 对每个实例都会抱怨很长时间。您对没有模板参数的 fixed_string 的想法可能有道理。我做完晚饭再试试。
  • @Nicole - 你是否在 g++ 中声明了 Member 对象?如果没有 Member 声明,编译器可能不会进行检查。
  • 可以将 CTAD 用于(非类型)模板参数。很好:如果没有模板参数且没有动态分配,将很难实现 fixed_string
  • @Max66 你说的很对。我不确定这个例子是如何遗漏的。我想是我编辑的一个怪癖。很抱歉它不见了,但它真的只是为了背景。在我看来,主要问题是如何定义一个 fixed_string 类。
  • @Davis 这是个好主意。我添加了一个用户自定义的模板推导指南,错误信息没有任何变化。我添加了 template<:size_t n> fixed_string(const fixed_string&) -> fixed_string;在现有 CTAD 指南之后。
猜你喜欢
  • 1970-01-01
  • 2021-04-28
  • 2021-06-18
  • 2013-06-26
  • 1970-01-01
  • 1970-01-01
  • 2012-03-16
  • 2022-11-21
  • 1970-01-01
相关资源
最近更新 更多