带模板参数的函数调用
Function call with template parameter
我写了一个简单的class模板:
template <class T>
class my_class
{
public:
my_class(T value)
: my_Value(value)
{
}
private:
T my_Value;
};
现在我可以在一个简单的函数签名中使用这个模板,例如:my_function(my_class<std::string> my_string)
当我想调用函数时,我可以很容易地使用它:
auto my_instance = my_class<std::string>("my value");
my_function(my_instance);
但是我想实现的是这样的函数调用:
my_function("my value")
我的 class 模板应该为我隐式转换为模板类型。我想我需要某种运算符重载。
例如,std:optional
可以这样做。
您必须添加接受类型可转换为您的 T
的构造函数。
C++20 之前的“经典”方法是使用 SFINAE 和 std::enable_if
:
template <typename T>
class my_class
{
public:
template <typename U, typename = std::enable_if_t<std::is_constructible_v<T,U>>>
my_class(U&& arg) : my_Value(std::forward<U>(arg))
{}
...
使用最新标准 (C++20),您可以使用概念并简化您的代码:
template <typename T>
class my_class
{
public:
template <typename U>
my_class(U&& arg) requires(std::is_constructible_v<T,U>)
: my_Value(std::forward<U>(arg))
{}
...
或者更简单:
template <typename T, typename U>
concept constructible_to = std::constructible_from<U, T>;
template <typename T>
class my_class
{
public:
template <constructible_to<T> U>
my_class(U&& arg)
: my_Value(std::forward<U>(arg))
{}
...
您只能进行一次隐式用户转化,因此您对 const char*
的调用无效。
有几个选项,
为my_class添加另一个构造函数
my_class(T value) : my_Value(value) {}
template <typename U, std::enable_if_t<std::is_convertible<U, T>, int> = 0>
my_class(U value) : my_Value(value) {}
为 my_function、
添加重载
void my_function(my_class<std::string> my_string)
void my_function(const char* s) { return my_function(my_class<std::string>{s}); }
更改调用站点以使用 std::string
:
调用它
my_function(std::string("my value"))
using namespace std::string_literals;
my_function("my value"s)
问题描述如下:
Implicit conversions - cppreference.com
Order of the conversions
Implicit conversion sequence consists of the following, in this order:
zero or one standard conversion sequence;
zero or one user-defined conversion;
zero or one standard conversion sequence.
When considering the argument to a constructor or to a user-defined conversion function, only a standard conversion sequence is allowed (otherwise user-defined conversions could be effectively chained). When converting from one built-in type to another built-in type, only a standard conversion sequence is allowed.
您当前的代码需要两个隐式用户定义的转换链:从 const char *
到 std::string
,然后从 std::string
到 my_class<std::string>
。
要解决这个问题,你必须减少这条链。所以基本上你需要提供构造函数,它允许将字符串文字转换为你的 my_class<std::string>
.
PiotrNycz
已提供解决方案:
template <class T>
class my_class
{
public:
my_class(const T& value)
: my_Value(value)
{
}
template <typename U, typename = std::enable_if_t<std::is_constructible_v<T,U>>>
my_class(U&& arg) : my_Value(std::forward<U>(arg))
{}
private:
T my_Value;
};
正如其他人已经解释的那样,您的问题是您希望连续进行两次隐式转换(字符串文字 (char const*
) => std::string
=> my_class<std::string>
)而只允许一个。
已经解释了如何将此链减少为一条的几种方法,但还有一种方法:只需将 std::string
直接传递给您的函数而不是字符串文字
using namespace std::string_literals;
my_function("my value"s);
注意 s
从字符串文字创建 std::string
。您需要使用该命名空间才能访问它。
我写了一个简单的class模板:
template <class T>
class my_class
{
public:
my_class(T value)
: my_Value(value)
{
}
private:
T my_Value;
};
现在我可以在一个简单的函数签名中使用这个模板,例如:my_function(my_class<std::string> my_string)
当我想调用函数时,我可以很容易地使用它:
auto my_instance = my_class<std::string>("my value");
my_function(my_instance);
但是我想实现的是这样的函数调用:
my_function("my value")
我的 class 模板应该为我隐式转换为模板类型。我想我需要某种运算符重载。
例如,std:optional
可以这样做。
您必须添加接受类型可转换为您的 T
的构造函数。
C++20 之前的“经典”方法是使用 SFINAE 和 std::enable_if
:
template <typename T>
class my_class
{
public:
template <typename U, typename = std::enable_if_t<std::is_constructible_v<T,U>>>
my_class(U&& arg) : my_Value(std::forward<U>(arg))
{}
...
使用最新标准 (C++20),您可以使用概念并简化您的代码:
template <typename T>
class my_class
{
public:
template <typename U>
my_class(U&& arg) requires(std::is_constructible_v<T,U>)
: my_Value(std::forward<U>(arg))
{}
...
或者更简单:
template <typename T, typename U>
concept constructible_to = std::constructible_from<U, T>;
template <typename T>
class my_class
{
public:
template <constructible_to<T> U>
my_class(U&& arg)
: my_Value(std::forward<U>(arg))
{}
...
您只能进行一次隐式用户转化,因此您对 const char*
的调用无效。
有几个选项,
为my_class添加另一个构造函数
my_class(T value) : my_Value(value) {} template <typename U, std::enable_if_t<std::is_convertible<U, T>, int> = 0> my_class(U value) : my_Value(value) {}
为 my_function、
添加重载void my_function(my_class<std::string> my_string) void my_function(const char* s) { return my_function(my_class<std::string>{s}); }
更改调用站点以使用
调用它std::string
:my_function(std::string("my value")) using namespace std::string_literals; my_function("my value"s)
问题描述如下:
Implicit conversions - cppreference.com
Order of the conversions
Implicit conversion sequence consists of the following, in this order:
zero or one standard conversion sequence;
zero or one user-defined conversion;
zero or one standard conversion sequence.
When considering the argument to a constructor or to a user-defined conversion function, only a standard conversion sequence is allowed (otherwise user-defined conversions could be effectively chained). When converting from one built-in type to another built-in type, only a standard conversion sequence is allowed.
您当前的代码需要两个隐式用户定义的转换链:从 const char *
到 std::string
,然后从 std::string
到 my_class<std::string>
。
要解决这个问题,你必须减少这条链。所以基本上你需要提供构造函数,它允许将字符串文字转换为你的 my_class<std::string>
.
PiotrNycz
已提供解决方案:
template <class T>
class my_class
{
public:
my_class(const T& value)
: my_Value(value)
{
}
template <typename U, typename = std::enable_if_t<std::is_constructible_v<T,U>>>
my_class(U&& arg) : my_Value(std::forward<U>(arg))
{}
private:
T my_Value;
};
正如其他人已经解释的那样,您的问题是您希望连续进行两次隐式转换(字符串文字 (char const*
) => std::string
=> my_class<std::string>
)而只允许一个。
已经解释了如何将此链减少为一条的几种方法,但还有一种方法:只需将 std::string
直接传递给您的函数而不是字符串文字
using namespace std::string_literals;
my_function("my value"s);
注意 s
从字符串文字创建 std::string
。您需要使用该命名空间才能访问它。