简体   繁体   中英

How to template specialize a function based on member variable existence

Here is a simple example of what I want, but I don't know how to make the functions unambiguous. I am using echo to check the integrity of the type of the member variable for SFINAE and echo back void as the return type.

// Example program
#include <iostream>
#include <string>
#include <type_traits>

namespace detail {
    struct X {
        int x;
    };
    
    struct Y {
        int y;
    };
    
    template <typename V, typename... T>
    using echo = V;
    
    template <typename T>
    echo<void, decltype(std::declval<T>().x)> template_print(T& t) {
        std::cout << "x = " << t.x << std::endl;
    }
    
    template <typename T>
    echo<void, decltype(std::declval<T>().y)> template_print(T& t) {
        std::cout << "y = " << t.y << std::endl;
    }
}

int main()
{
    detail::X a{.x = 1};
    detail::Y b{.y = 2};
    detail::template_print(a);
    detail::template_print(b);
    return 0;
}

I would not call this an issue of ambiguity, but of redefinition.

You can fix the issue you are having if you change the implementation of your echo alias template from "direct" to "indirect" as in the following snippet.

template <typename T, typename... Ts>
struct Echo
{
    using type = T;
};
template <typename T, typename... Ts>
using echo = typename Echo<T, Ts...>::type;

Note that some may advise that you use std::void_t , but that would not work here either - for the exact same reason.

The issue is a bit complex, but you can avoid it by using an indirect alias template (like the one above that eventually resolves to the nested type) rather than a direct alias template.

At risk of shilling my own talk, the only place I've seen any sort of explanation of this is in the first part of this CppCon 2021 video .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM