You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++可变using声明引入基类转换运算符:语法与可行性

可变参数using声明引入基类转换运算符的正确语法

问题描述

我定义了struct overloaded,让它继承多个can_convert_to<T>模板实例(每个模板参数Ts都被包装成can_convert_to<Ts>作为基类)。现在想把所有基类的operator T()转换运算符都引入到overloaded中,尝试用可变参数的using声明但语法错误,请问这个特性在C++中是否可行?正确语法是什么?

原代码中的错误关键行:

using can_convert_to<Ts>::operator typename can_convert_to<Ts>::type()...; 

解答

这个特性在C++17及以后完全可行,正确的using声明语法需要简化:因为can_convert_to<T>中的转换运算符就是operator T(),而Ts本身就是can_convert_to<Ts>::type的别名,所以直接引用基类的operator Ts即可,不需要额外的typename和()。

修正后的核心代码行

using can_convert_to<Ts>::operator Ts...;

语法说明

  • 转换运算符的using声明语法为using BaseClass::operator TargetType;,末尾不需要加(),这是原代码的核心语法错误。
  • C++17支持可变参数的using声明展开,能一次性将所有基类的对应转换运算符引入到派生类作用域中,解决基类成员名称隐藏的问题。

完整修正代码

#include <string>
#include <concepts> // 需包含此头文件以使用std::same_as

template <typename T> 
struct can_convert_to 
{ 
    using type = T;
    operator T(); // 概念检查仅需声明,无需定义
};

template<class... Ts>  
struct overloaded : can_convert_to<Ts>... { 
    // 修正后的可变参数using声明
    using can_convert_to<Ts>::operator Ts...; 
};

template<typename... Ts> 
auto any_of() {
    return overloaded<Ts...>{};
};

template<typename T>
concept has_set = requires(T t) {
    { t.set(any_of<std::string_view, std::string, char*>()) } -> std::same_as<void>;
};

struct Foo {};
static_assert(!has_set<Foo>);

struct Bar {
    void set(std::string_view);
    void set(std::string);
};
static_assert(has_set<Bar>);

struct Baz {
    void set(std::string);
};
static_assert(has_set<Baz>);

struct Bazz {
    void set(char const *);
};
static_assert(has_set<Bazz>); // char*可隐式转换为const char*,断言成立

补充说明

  • 原代码遗漏了<concepts>头文件,std::same_as依赖此头文件支持。
  • can_convert_to<T>::operator T()仅需声明无需定义,因为概念检查是编译期行为,不会实际调用该运算符。
  • Bazz的set接受const char*,而any_of提供的char*可隐式转换为const char*,因此对应的静态断言能够成立。

内容的提问来源于stack exchange,提问作者Markus W.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 20:23:13