C++17的可选和可变顺序函数参数
Optional and variably ordered function arguments with C++17
我正在努力改进串行端口类的构造函数。目前有许多重载来处理不同的场景(端口、波特率、数据位、奇偶校验、创建时打开、回调等(。为了允许这个类的用户以任意顺序只传递他/她需要的参数,我开始如下:
#include <iostream>
#include <string>
#include <tuple>
template <typename T, typename Tuple>
struct has_type;
template <typename T, typename... Us>
struct has_type<T, std::tuple<Us...>> : std::disjunction<std::is_same<T, Us>...> {};
template <typename ...UnorderedArgs>
std::string getPort(std::tuple<UnorderedArgs...> arg_set)
{
if constexpr (has_type<std::string, std::tuple<UnorderedArgs...>>::value)
return std::get<std::string &&>(std::move(arg_set));
else
return "NotSet";
}
class SerialPort
{
public:
template <typename... Args>
SerialPort(Args ...args) :
SerialPort(std::forward_as_tuple(std::move(args)...))
{}
template <typename ...UnorderedArgs>
SerialPort(std::tuple<UnorderedArgs...> arg_set) :
SerialPort(getPort(std::move(arg_set)))
{}
SerialPort(const std::string &port) // [X]
{
std::cout << "SerialPort " << port << std::endl;
}
};
int main()
{
std::string port = "/dev/tty";
SerialPort sp(1, port); // without 1 the compiler would use [X]
return 0;
}
此代码将端口设置为NotSet
,因此带有if constexpr
的部件无法按预期工作。如何解决这个问题?
此代码将端口设置为
NotSet
,因此带有if constexpr
的部件无法按预期工作。如何解决这个问题?
如果引用是个问题:当你检查has_type
中是否存在std::string
时,std::string
存在,但有引用(std::move()
给出的&&
,如果我没有错的话(。
解决方案:删除引用
template <typename T, typename... Us>
struct has_type<T, std::tuple<Us...>>
: std::disjunction<std::is_same<T, std::remove_reference_t<Us>>...> {};
// ..................................^^^^^^^^^^^^^^^^^^^^^^^^^^^
--编辑--
正如Jarod42所指出的(谢谢!(,这样has_type
这个名称就不再正确了。
也许你需要一个has_type
来检测类型的存在,同时检查引用。。。
也许最好保持原始的has_type
,并使用std::remove_reference_t
调用它
// ............................................VVVVVVVVVVVVVVVVVVVVVVV
if constexpr (has_type<std::string, std::tuple<std::remove_reference_t<UnorderedArgs>...>>::value)
return std::get<std::string &&>(std::move(arg_set));
else
return "NotSet";
为什么要限制自己使用C++提供的语法?这个问题需要对构建器模式和流畅的API进行修改。
使用类似的东西:
class serial_port_options
{
/* private fields to hold options */
public:
serial_port_options& set_port( int );
serial_port_options& set_baudrate( int );
serial_port_options& set_data_bits( int );
serial_port_options& set_parity( bool );
serial_port_options& set_open_on_creation( bool );
serial_port_options& set_callbacks( CALLBACK );
int get_port() const;
int get_baudrate() const;
int get_data_bits() const;
bool get_parity() const;
bool get_open_on_creation() const;
CALLBACK get_callbacks() const;
};
class SerialPort
{
public:
SerialPort(const serial_port_options&);
/* other logic and public interface */
};
使用上面的,你可以建立你的选项对象:
serial_port_options options;
options.set_port(80).set_baudrate(65536).set_data_bits(7)
.set_parity(false).set_open_on_creation(true);
SerialPort port(options);
相关文章:
- 函数调用中参数的顺序重要吗
- 优先顺序:智能指针和类析构函数
- C++成员的析构函数顺序与shared_ptr
- C++:使用方法调用析构函数的顺序是什么?
- 以 f() + g() 调用顺序的 C++ 函数
- 为什么用户定义的函数不按照给定的顺序对相同长度的元素进行排序?
- 有没有办法保证析构函数的相对顺序?
- 函数模板实例化、替换和重载解析的顺序是什么?
- 类内初始化与构造函数初始化列表的顺序
- 递归函数的执行顺序
- 运算符 new 的执行顺序和构造函数的参数
- 如果在 C++ 构造函数中以错误的顺序初始化对象数据,会发生什么类型的错误
- std::bind() 参数列表中函子的执行顺序(可能与函数参数的求值顺序无关)
- 构造函数中没有参数的对象类成员按什么顺序初始化?
- std::unique_ptr析构函数顺序
- C++17的可选和可变顺序函数参数
- OpenMP 不在 for 循环中的顺序函数的并行化
- 递归C++字母顺序函数重复返回相同的值
- C++-销毁顺序-函数的静态成员在主类析构函数之前被销毁
- 构造函数执行顺序/顺序:函数中静态变量(类实例)的依赖初始化