函数模板不适用于字符串文字

Ada*_*kis 8 c++ c++11 c++14 c++17

背景:

我工作的一个查询DSL那会解析与表达==<通过运算符重载等,回油过滤器的对象。

问题:

与字符串文字一起使用时,我的模板方法失败。我尝试提供采用的模板的特定实例化std::stringchar但是似乎都行不通。

代码如下。导致main中问题的行标有注释。我尝试过的替代解决方案在代码中已注释掉。

可以在此处找到相同代码的可运行repl 。

我确实知道可以手动包装字符串文字std::string("text"),但是我希望能够使用纯字符串文字(如果可能的话)。

#include <iostream>

template<typename T>
struct Filter;

struct Field
{
    Field(const std::string &val): name(val) { }
    Field(std::string &&val): name(std::move(val)) { }
    std::string name;

    // template <signed N>
    // Filter<std::string> operator==(const char (&val) [N]);

    template <typename T>
    Filter<T> operator==(const T &val);
};

template <typename T>
Filter<T> Field::operator==(const T &val)
{
    return Filter<T>{ *this, val, "==" };
}

// template <signed N>
// Filter<std::string> Field::operator==(const char (&val) [N])
// {
//   return Filter<std::string>{ *this, std::string(val), "==" };
// }

// template <>
// Filter<std::string> Field::operator==<std::string>(const std::string &val)
// {
//     return Filter<std::string>{ *this, val, "==" };
// }


template<typename T>
struct Filter
{
    Field f;
    T val;
    std::string op;
};

int main() {
  Field f1 { "field1" };
  Field f2 { "field1" };
  std::cout << (f1 == 1).val;
  std::cout << (f1 == "Hello").val;  // <--- the source of my problems
}
Run Code Online (Sandbox Code Playgroud)

Jar*_*d42 9

问题是c数组不可复制,因此

Filter<char [6]>{ *this, val, "==" }; // Error
Run Code Online (Sandbox Code Playgroud)

你超载是正确的,但Filter需要重新排序并确定之前您的operator==过载。重载返回Filter<T>取决于T,因此在这种情况下,Filter可以推迟的定义。但是,当您返回时Filter<std::string>,编译器需要预先进行实际定义Filter

#include <iostream>

template<typename T>
struct Filter;

struct Field
{
    Field(const std::string &val): name(val) { }
    Field(std::string &&val): name(std::move(val)) { }
    std::string name;

    template <std::size_t N> Filter<std::string> operator==(const char (&val) [N]);

    template <typename T>
    Filter<T> operator==(const T &val);
};

template<typename T>
struct Filter
{
    Field f;
    T val;
    std::string op;
};

template <typename T>
Filter<T> Field::operator==(const T &val)
{
    return Filter<T>{ *this, val, "==" };
}

template <std::size_t N>
Filter<std::string> Field::operator==(const char (&val) [N])
{
   return Filter<std::string>{ *this, std::string(val), "==" };
}

int main() {
  Field f1 { "field1" };
  Field f2 { "field1" };
  std::cout << (f1 == 1).val;
  std::cout << (f1 == "Hello").val;
}

Run Code Online (Sandbox Code Playgroud)

演示版

  • 由于Filter &lt;T&gt;取决于T,因此定义可能会被推迟,而Filter &lt;std :: string&gt;并不取决于N,因此应该知道定义。 (2认同)