将std :: variant转换为另一个具有超类型的std :: variant

时间:2017-11-09 13:34:20

标签: c++ type-conversion c++17 variant

我有一个std::variant我希望转换为另一个std::variant,其中包含超类型的template <typename ToVariant, typename FromVariant> ToVariant ConvertVariant(const FromVariant& from) { ToVariant to = std::visit([](auto&& arg) -> ToVariant {return arg ; }, from); return to; } int main() { std::variant<int , double> a; a = 5; std::variant <std::string, double, int> b; b = ConvertVariant<decltype(b),decltype(a)>(a); return 0; } 。有没有一种方法可以让我简单地将一个分配给另一个?

b = a

我希望能够简单地编写std来进行转换,而不是通过这个复杂的转换设置。不会污染b = a命名空间。

编辑:只需编写error C2679: binary '=': no operator found which takes a right-hand operand of type 'std::variant<int,double>' (or there is no acceptable conversion) note: while trying to match the argument list '(std::variant<std::string,int,double>, std::variant<int,double>)' 就会出现以下错误:

import UIKit
import SpriteKit
import GameplayKit
import FBSDKLoginKit
import Firebase
import GoogleSignIn

class AuthViewController: SKScene, SKViewDelegate, FBSDKLoginButtonDelegate, GIDSignInUIDelegate {





override func didMove(to view: SKView) {





    //add facebook sign in button

    let loginButton = FBSDKLoginButton()

    view.addSubview(loginButton)
   // addChild(loginButton)


    loginButton.frame = CGRect(x: 16, y: 50, width: (view.frame.width) - 32, height: 50)
    loginButton.delegate = self as FBSDKLoginButtonDelegate

    loginButton.readPermissions = ["email", "public_profile"]


    //add Google sign-in button

    let googleButton = GIDSignInButton()

    googleButton.frame = CGRect(x: 16, y: 50 + 66, width: (view.frame.width) - 32, height: 50)

    view.addSubview(googleButton)

    GIDSignIn.sharedInstance().uiDelegate = self



}

func loginButtonDidLogOut(_ loginButton: FBSDKLoginButton!) {
    print("Did log out of facebook")
}

func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
    if error != nil {
        print(error)

        return
    }
    else {
        //skView.presentScene(location, transition: SKTransition.fade(withDuration: 5))



        print("Successfully logged in with facebook...")
    }

    func showEmailAddress() {

        let accessToken = FBSDKAccessToken.current()

        guard let accessTokenString = accessToken?.tokenString else { return }



        let credentials = FacebookAuthProvider.credential(withAccessToken: accessTokenString)

        Auth.auth().signIn(with: credentials) { (user, error) in


            if error != nil {
                print("Something went wrong with our FB user: ", error ?? "")
                return
            }





            print("Successfully logged in with our users:", user ?? "")
        }


        FBSDKGraphRequest(graphPath: "/me", parameters: ["fields": "id, name, email"]).start { (connection, result, err) in

            if err != nil {
                print("Fail to return graph request:", err ?? "")

                return
            }

            print(result ?? "")

        }
    }

}

2 个答案:

答案 0 :(得分:7)

这是Yakk的第二个选项的实现:

template <class... Args>
struct variant_cast_proxy
{
    std::variant<Args...> v;

    template <class... ToArgs>
    operator std::variant<ToArgs...>() const
    {
        return std::visit([](auto&& arg) -> std::variant<ToArgs...> { return arg ; },
                          v);
    }
};

template <class... Args>
auto variant_cast(const std::variant<Args...>& v) -> variant_cast_proxy<Args...>
{
    return {v};
}

您可能希望对其进行微调以转发语义。

正如您所看到的,它的使用很简单:

std::variant<int, char> v1 = 24;
std::variant<int, char, bool> v2;

v2 = variant_cast(v1);

答案 1 :(得分:1)

选项:

  • 编写您自己的variant类型,可能继承自std::variant,实现operator=并按您希望的方式构建。必须完成一些工作,因为variant的构造函数可以执行SFINAE技巧,这些技巧可能无法与您的变体类型一起正常工作;为此,您希望自己做一些SFINAE转发到基础变体而不是裸using声明。

  • 编写一个更好的ConvertVariant,不需要列出源/目标类型。您将返回一个转换助手模板类型,该模板类型包含一个operator std::variant<Ts...>()&&源变量,该变量调用与您的ConvertVariant非常相似的内容。