Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
312 views
in Technique[技术] by (71.8m points)

c++ - SFINAE : Delete a function with the same prototype

I wonder what is the difference between this code that works :

#include <type_traits>
#include <iostream>

template<typename T> using is_ref = std::enable_if_t<std::is_reference_v<T>, bool>;
template<typename T> using is_not_ref = std::enable_if_t<!std::is_reference_v<T>, bool>;

template<typename T, is_ref<T> = true>
void foo(T&&) {
    std::cout << "ref" << std::endl;
}

template<typename T, is_not_ref<T> = true>
void foo(T&&) {
    std::cout << "not ref" << std::endl;
}

int main() {
    int a = 0;
    foo(a);
    foo(5);
}

and this one that does not work :

#include <type_traits>
#include <iostream>

template<typename T> using is_ref = std::enable_if_t<std::is_reference_v<T>, bool>;
template<typename T> using is_not_ref = std::enable_if_t<!std::is_reference_v<T>, bool>;

template<typename T, typename = is_ref<T>>
void foo(T&&) {
    std::cout << "ref" << std::endl;
}

template<typename T, typename = is_not_ref<T>>
void foo(T&&) {
    std::cout << "not ref" << std::endl;
}

int main() {
    int a = 0;
    foo(a);
    foo(5);
}

What is the true difference between typename = is_ref<T> and is_ref<T> = true ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

If you remove the default template arguments, it'll become clear what the difference is. Function declarations cannot differ in just their defaults. This is ill-formed:

void foo(int i = 4);
void foo(int i = 5);

And likewise this is ill-formed:

template <typename T=int> void foo();
template <typename T=double> void foo();

With that in mind, your first case:

template<typename T, is_ref<T>>
void foo(T&&);

template<typename T, is_not_ref<T>>
void foo(T&&);

The two declarations here are unique because the second template parameter differs between the two declarations. The first has a non-type template parameter whose type is std::enable_if_t<std::is_reference_v<T>, bool> and the second has a non-type template parameter whose type is std::enable_if_t<!std::is_reference_v<T>, bool>. Those are different types.

Whereas, your second case:

template<typename T, typename>
void foo(T&&);

template<typename T, typename>
void foo(T&&)

This is clearly the same signature - but we've just duplicated it. This is ill-formed.


See also cppreference's explanation.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...