dimanche 14 novembre 2021

SFINAE: Duplicate Definitions?

I have the following code:

#include <iostream>

/*
template <class A, std::enable_if_t<!std::is_same_v<A, double>, bool> = true>
void test() {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}

template <class A, std::enable_if_t<std::is_same_v<A, double>, bool> = true>
void test() {
    std::cout << "SFINAE" << std::endl;
}
*/

template <class A, typename = std::enable_if_t<!std::is_same_v<A, double>>>
void test() {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}

template <class A, typename = std::enable_if_t<std::is_same_v<A, double>>>
void test() {
    std::cout << "SFINAE" << std::endl;
}

int main() {
    test<int>();
    test<double>();
}

Compiler complains

test_function_templ.cpp:21:6: error: redefinition of ‘template<class A, class> void test()’
   21 | void test() {
      |      ^~~~
test_function_templ.cpp:16:6: note: ‘template<class A, class> void test()’ previously declared here
   16 | void test() {
      |      ^~~~
test_function_templ.cpp: In function ‘int main()’:
test_function_templ.cpp:27:15: error: no matching function for call to ‘test<double>()’
   27 |  test<double>();
      |               ^
test_function_templ.cpp:16:6: note: candidate: ‘template<class A, class> void test()’
   16 | void test() {
      |      ^~~~
test_function_templ.cpp:16:6: note:   template argument deduction/substitution failed:
In file included from /opt/rh/devtoolset-10/root/usr/include/c++/10/bits/move.h:57,
                 from /opt/rh/devtoolset-10/root/usr/include/c++/10/bits/nested_exception.h:40,
                 from /opt/rh/devtoolset-10/root/usr/include/c++/10/exception:148,
                 from /opt/rh/devtoolset-10/root/usr/include/c++/10/ios:39,
                 from /opt/rh/devtoolset-10/root/usr/include/c++/10/ostream:38,
                 from /opt/rh/devtoolset-10/root/usr/include/c++/10/iostream:39,
                 from test_function_templ.cpp:1:
/opt/rh/devtoolset-10/root/usr/include/c++/10/type_traits: In substitution of ‘template<bool _Cond, class _Tp> using enable_if_t = typename std::enable_if::type [with bool _Cond = false; _Tp = void]’:
test_function_templ.cpp:15:20:   required from here
/opt/rh/devtoolset-10/root/usr/include/c++/10/type_traits:2554:11: error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
 2554 |     using enable_if_t = typename enable_if<_Cond, _Tp>::type;
      |           ^~~~~~~~~~~

If I use the first set of function templates (commented in the code) test(), it compiles and runs as expected.

Questions

  1. I thought for the 2nd set of function templates, calling test<int>() would instantiate test<int, void>() and calling test<double>() would instantiate test<double, void>(). But compiler seems like seeing two duplicate template functions?

  2. Why the first set of function templates doesn't have any issue while second set does?

Aucun commentaire:

Enregistrer un commentaire