如何实现混合可调用对象与变量引用初始化C++的Values类?
解决C++ Values类混合可调用对象与值初始化的问题
你的问题核心是原构造函数用全局concept约束所有参数必须同类型(全可调用或全值),导致混合初始化时concept冲突。解决思路是放弃对整个参数包的统一约束,转而逐个参数判断并处理,通过辅助函数将所有参数统一包装为可调用对象(值/引用包装成返回自身的lambda,可调用对象直接保留)。
具体实现步骤
- 定义辅助concept区分参数类型
#include <concepts> #include <functional> #include <tuple> #include <type_traits> // 判断是否是可调用对象(排除引用类型) template<typename T> concept CallableObj = std::invocable<T> && !std::is_reference_v<T>; // 判断是否是值或引用类型(非可调用对象) template<typename T> concept ValueOrRef = !CallableObj<T>;
- 重构Values类的构造与存储逻辑
template<typename... RetTypes> class Values { private: // 统一存储可调用对象,返回对应类型的值 std::tuple<std::function<RetTypes()>&&...> storages; // 包装值/引用为可调用对象 template<ValueOrRef T> static auto wrap(T&& val) { if constexpr (std::is_lvalue_reference_v<T>) { // 左值引用:返回捕获引用的lambda,保持引用语义 return [&val]() -> decltype(auto) { return val; }; } else { // 右值:移动捕获,存储副本 return [val = std::forward<T>(val)]() -> decltype(auto) { return val; }; } } // 可调用对象直接转发,无需包装 template<CallableObj F> static auto wrap(F&& func) { static_assert(std::is_invocable_r_v<std::tuple_element_t<0, std::tuple<RetTypes...>>, F>, "Callable return type mismatch"); return std::forward<F>(func); } public: // 可变参数构造函数,无全局concept约束,逐个处理参数 template<typename... Ts> requires (sizeof...(Ts) == sizeof...(RetTypes)) Values(Ts&&... args) : storages(wrap(std::forward<Ts>(args))...) {} // 获取第N个值的示例接口 template<std::size_t N> RetTypes get() { return std::get<N>(storages)(); } };
测试混合初始化场景
#include <iostream> #include <cstdlib> int main() { int x = 42; auto rand_func = []() { return std::rand(); }; // 混合初始化:左值引用 + 可调用对象 Values<int, int> v3(x, rand_func); std::cout << v3.get<0>() << std::endl; // 输出42 std::cout << v3.get<1>() << std::endl; // 输出随机数 // 修改原变量,验证引用语义 x = 100; std::cout << v3.get<0>() << std::endl; // 输出100 return 0; }
关键说明
- 放弃对整个参数包的concept约束,改为在
wrap函数中用concept分支处理单个参数,避免构造函数之间的冲突。 - 通过
std::function实现类型擦除,统一存储所有可调用对象(包括包装后的值/引用)。 - 保留了引用语义:如果传入左值引用,包装后的lambda会捕获引用,修改原变量会影响Values的返回值;如果传入右值,则会存储副本。
内容的提问来源于stack exchange,提问作者Nathan29006781
相关产品推荐
相关产品推荐

