gpt4 book ai didi

c++ - 为什么带有 initializer_list 参数的模板对字符串的行为不正常?

转载 作者:搜寻专家 更新时间:2023-10-31 02:20:00 31 4
gpt4 key购买 nike

正在关注 C++ Most efficient way to compare a variable to multiple values? ,我正在尝试使用 initializer_list 构建模板函数作为论据。当我只使用字符串时就会出现问题。我有以下代码:

函数.hpp

template <typename T>
bool is_in(T const& val, initializer_list<T> const& liste)
{
for (const auto& i : liste)
if (val == i) return true;
return false;
};

main.cpp

#include "functions.hpp"
using namespace std;
int main()
{
string test("hello");
if (is_in(test, {"foo", "bar"}))
cout << "good" << endl;
else
cout << "bad" << endl;
return 0;
}

我收到以下错误:

main.cpp: In function ‘int main()’:
main.cpp:18:34: error: no matching function for call to ‘is_in(std::string&, <brace-enclosed initializer list>)’
main.cpp:18:34: note: candidate is:
In file included from personnage.hpp:11:0,
from main.cpp:1:
functions.hpp:16:6: note: template<class T> bool is_in(const T&, const std::initializer_list<_Tp>&)
functions.hpp:16:6: note: template argument deduction/substitution failed:
main.cpp:18:34: note: deduced conflicting types for parameter ‘_Tp’ (‘std::basic_string<char>’ and ‘const char*’)

我不明白的是:什么时候而不是 string我用 intdouble在我的 main ,一切都很顺利......一个快速而肮脏的解决方法是声明is_in仅作为字符串的函数,但不是很令人满意。

有谁知道如何保持模板和使用字符串一样吗?

最佳答案

在你的函数模板中

template <typename T>
bool is_in(T const& val, initializer_list<T> const& liste)

两个参数都会参与template argument deduction ,并且从每个推导出的类型是不同的。 T被扣除为std::string从第一个参数和 char const *从第二个开始(在模板参数推导期间不考虑用户定义的转换,因此从 char const *std::string 的隐式转换不会出现在图片中),这会导致编译错误。

有多种方法可以解决此问题。一种是构建 string在你传递给 is_inbraced-init-list 中,如果您可以使用 C++14 的 std::string_literals ,这可以非常简洁地完成.

using namespace std::string_literals;

if (is_in(test, {"foo"s, "bar"s}))
// ^ ^

另一种方法是构造一个 initializer_list<string>并将其传递给 is_in

if (is_in(test, initializer_list<string>{"foo", "bar"}))

您还可以重新定义 is_in这样两种参数类型的模板类型参数是不同的,毕竟你不关心它们是否相同,你只需要它们可以通过 operator== 进行比较

template <typename T, typename U>
bool is_in(T const& val, initializer_list<U> const& liste)

另一种选择是防止其中一个函数参数参与模板参数推导。

template<typename T>
struct identity
{ using type = T; };

template <typename T>
bool is_in(T const& val, initializer_list<typename identity<T>::type> const& liste)

T之上在第二个参数中是一个 non-deduced context , 因此只有第一个参数参与模板参数推导。


最后,is_in可以替换为 std::any_of .

auto elems = {"foo", "bar"};
if (any_of(begin(elems), end(elems), [&](string const& s) { return s == test; }))

如果你想避免 lambda 表达式样板,你可以使用 boost::algorithm::any_of_equal .

auto elems = {"foo", "bar"};
if (boost::algorithm::any_of_equal(elems, test))

关于c++ - 为什么带有 initializer_list 参数的模板对字符串的行为不正常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33200019/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com