从结构体隐式转换

Mak*_*ico 0 c++ struct casting variant

这是我的结构,它在创建变量时使用隐式转换。

#include <string>
#include <variant>

using namespace std;
using val = variant<int, string, double, bool, long, long long, long double>;

struct value
{
    val innerVal;
    value():innerVal(""){}
    value(const val &c) : innerVal(c) {}

    template <typename T>
    operator T()
    {
          return get<T>(innerVal);
    }

    template <typename V>
    value &operator=(const V &t)
    {
        innerVal = t;
        return *this;
    }
};
Run Code Online (Sandbox Code Playgroud)

这就是我在构造变量时使用它的方式,它工作正常,但是当我分配一个已经创建的变量来value构造它时,它会给出错误。

int main(int argc, char* argv[])
{
    value h;
    h = "String";
    string m = h;// Here works fine
     string b = "different";
     b = h;//Here it gives error 
}
Run Code Online (Sandbox Code Playgroud)

编译错误



use of overloaded operator '=' is 
ambiguous (with operand types 
'std::__ndk1::string' (aka 
'basic_string<char, char_traits<char>, 
allocator<char> >') and 'value')

        b = h;
Run Code Online (Sandbox Code Playgroud)

我想隐式构造变量而不会遇到此错误有人可以解释如何解决此问题。

0xb*_*ann 6

该分配b = h不明确,因为std::string具有不同的operator=. 因为您有一个模板化转换运算符,所以您的编译不知道要采用哪个operator=重载std::string

您可以限制允许的转换类型,value以仅允许隐式转换为成员类型之一variant。以下结构体将使用折叠表达式提供一个布尔值,告诉我们 type 是否T包含在Type的模板参数中:

template<typename, typename>
struct has_template_param;

template<typename T, template<typename ...> typename Type, typename ...Ts>
struct has_template_param<T, Type<Ts...>> {
    static constexpr bool value = (... || std::is_same_v<T, Ts>);
};
Run Code Online (Sandbox Code Playgroud)

然后可以使用 SFINAE 约束模板化转换运算符:

template<typename T, typename = std::enable_if_t<has_template_param<T, val>::value>>
operator T() {
    return std::get<T>(innerVal);
}
Run Code Online (Sandbox Code Playgroud)

使用C++20概念,可以通过以下方式更方便地完成

template<typename T, typename Type>
concept has_param = has_template_param<T, Type>::value;
Run Code Online (Sandbox Code Playgroud)

template<has_param<val> T>
operator T() {
    return std::get<T>(innerVal);
}
Run Code Online (Sandbox Code Playgroud)

查看演示

  • 在某些情况下,概念方法不起作用(即目标类型可能接受两种不同的匹配类型),但对于“字符串”它有效。 (2认同)