使用模板的函数重载 - 仅在存在替代函数时应用 enable_if
Function overloading with templates - applying enable_if only when alternative function exists
我设法根据对象的等级为 std::ostream
重载了插入运算符。
我想扩展下面的例子。
当包含 A_new.h
时,它包含 A.h
... 在这种情况下,我正在检查对象的等级并调用 f_alterantive
或 f_old
。按预期工作:)
问题出现在直接包含A.h
时,那么f()
只有一个实例-f_old
。
如果直接通过A.h
包含了f()
的一个实例,那么它应该是所有对象的默认...(不仅对于rank > 1
,而且对于全部休息)
以下条件没有意义。
typename std::enable_if <(std::rank<T>::value > 1), int>::type = 0 >
我知道我需要指定检查是否存在另一个 f()
的条件:
类似于:
//goal: typename std::enable_if <((f_alternative_exist == false) || (std::rank<T>::value > 1 && f_alternative_exist == true) ), int>::type = 0 >
我找到了 similar question,但我仍然不确定如何使用 std::enable_if
#include <iostream>
#include <type_traits>
#include <sstream>
class Foo {
};
//--- alternative header A_new.h
//#include A.h
template< class T,
typename std::enable_if<(std::rank<T>::value == 1), int>::type = 0 >
void f(std::ostream& os, const T& value)
//f_alternative
{
os << "alternative function\n";
os << "rank == 1" << std::endl;
}
//----
//---- old header A.h
template < class T,
typename std::enable_if <(std::rank<T>::value > 1), int>::type = 0 >
//goal: typename std::enable_if <((f_alternative_exist == false) || (std::rank<T>::value > 1 && f_alternative_exist == true) ), int>::type = 0 >
void f(std::ostream& os, const T& value)
//f_old
{
os << "old function\n";
os << "rank > 1" << std::endl;
}
template <class T>
std::ostream& operator<<(std::ostream& os, const T& foo)
{
f<T>(os, foo);
return os;
}
//-----
int main()
{
Foo foo1[5];
Foo foo2[5][5];
std::cout << foo1;
std::cout << foo2;
return 0;
}
https://coliru.stacked-crooked.com/a/7f7ef7bda1805a36
你能告诉我如何指定 std::enable_if
在 f()
未超载时以及在所有情况下应该 运行 时工作吗?
一个可能的f_alternative_exist
如下
template <typename T>
std::false_type f_alternative_exist_f (std::ostream &, T const &, long);
template <typename T>
auto f_alternative_exist_f (std::ostream & os, T const & t, int)
-> decltype( f(os, t), std::true_type{} );
template <typename T>
using f_alternative_exist
= decltype(f_alternative_exist_f(std::declval<std::ostream &>(),
std::declval<T>(), 0));
template <typename T>
static constexpr bool f_alternative_exist_v
= f_alternative_exist<T>::value;
旧版本变为
template <typename T,
std::enable_if_t<(std::rank<T>::value > 1)
|| (false == f_alternative_exist_v<T>), int> = 0 >
void f (std::ostream & os, T const &)
{
os << "old function\n";
os << "rank > 1" << std::endl;
}
以下是完整编译C++14的例子
#include <iostream>
#include <type_traits>
#include <sstream>
class Foo
{ };
template <typename T>
std::false_type f_alternative_exist_f (std::ostream &, T const &, long);
template <typename T>
auto f_alternative_exist_f (std::ostream & os, T const & t, int)
-> decltype( f(os, t), std::true_type{} );
template <typename T>
using f_alternative_exist
= decltype(f_alternative_exist_f(std::declval<std::ostream &>(),
std::declval<T>(), 0));
template <typename T>
static constexpr bool f_alternative_exist_v
= f_alternative_exist<T>::value;
#if 0 // enable/disable
template <typename T,
std::enable_if_t<std::rank<T>::value == 1, int> = 0 >
void f (std::ostream & os, T const &)
{
os << "alternative function\n";
os << "rank == 1" << std::endl;
}
#endif
template <typename T,
std::enable_if_t<(std::rank<T>::value > 1)
|| (false == f_alternative_exist_v<T>), int> = 0 >
void f (std::ostream & os, T const &)
{
os << "old function\n";
os << "rank > 1" << std::endl;
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const T& foo)
{
f<T>(os, foo);
return os;
}
int main ()
{
Foo foo1[5];
Foo foo2[5][5];
std::cout << foo1;
std::cout << foo2;
}
我设法根据对象的等级为 std::ostream
重载了插入运算符。
我想扩展下面的例子。
当包含 A_new.h
时,它包含 A.h
... 在这种情况下,我正在检查对象的等级并调用 f_alterantive
或 f_old
。按预期工作:)
问题出现在直接包含A.h
时,那么f()
只有一个实例-f_old
。
如果直接通过A.h
包含了f()
的一个实例,那么它应该是所有对象的默认...(不仅对于rank > 1
,而且对于全部休息)
以下条件没有意义。
typename std::enable_if <(std::rank<T>::value > 1), int>::type = 0 >
我知道我需要指定检查是否存在另一个 f()
的条件:
类似于:
//goal: typename std::enable_if <((f_alternative_exist == false) || (std::rank<T>::value > 1 && f_alternative_exist == true) ), int>::type = 0 >
我找到了 similar question,但我仍然不确定如何使用 std::enable_if
#include <iostream>
#include <type_traits>
#include <sstream>
class Foo {
};
//--- alternative header A_new.h
//#include A.h
template< class T,
typename std::enable_if<(std::rank<T>::value == 1), int>::type = 0 >
void f(std::ostream& os, const T& value)
//f_alternative
{
os << "alternative function\n";
os << "rank == 1" << std::endl;
}
//----
//---- old header A.h
template < class T,
typename std::enable_if <(std::rank<T>::value > 1), int>::type = 0 >
//goal: typename std::enable_if <((f_alternative_exist == false) || (std::rank<T>::value > 1 && f_alternative_exist == true) ), int>::type = 0 >
void f(std::ostream& os, const T& value)
//f_old
{
os << "old function\n";
os << "rank > 1" << std::endl;
}
template <class T>
std::ostream& operator<<(std::ostream& os, const T& foo)
{
f<T>(os, foo);
return os;
}
//-----
int main()
{
Foo foo1[5];
Foo foo2[5][5];
std::cout << foo1;
std::cout << foo2;
return 0;
}
https://coliru.stacked-crooked.com/a/7f7ef7bda1805a36
你能告诉我如何指定 std::enable_if
在 f()
未超载时以及在所有情况下应该 运行 时工作吗?
一个可能的f_alternative_exist
如下
template <typename T>
std::false_type f_alternative_exist_f (std::ostream &, T const &, long);
template <typename T>
auto f_alternative_exist_f (std::ostream & os, T const & t, int)
-> decltype( f(os, t), std::true_type{} );
template <typename T>
using f_alternative_exist
= decltype(f_alternative_exist_f(std::declval<std::ostream &>(),
std::declval<T>(), 0));
template <typename T>
static constexpr bool f_alternative_exist_v
= f_alternative_exist<T>::value;
旧版本变为
template <typename T,
std::enable_if_t<(std::rank<T>::value > 1)
|| (false == f_alternative_exist_v<T>), int> = 0 >
void f (std::ostream & os, T const &)
{
os << "old function\n";
os << "rank > 1" << std::endl;
}
以下是完整编译C++14的例子
#include <iostream>
#include <type_traits>
#include <sstream>
class Foo
{ };
template <typename T>
std::false_type f_alternative_exist_f (std::ostream &, T const &, long);
template <typename T>
auto f_alternative_exist_f (std::ostream & os, T const & t, int)
-> decltype( f(os, t), std::true_type{} );
template <typename T>
using f_alternative_exist
= decltype(f_alternative_exist_f(std::declval<std::ostream &>(),
std::declval<T>(), 0));
template <typename T>
static constexpr bool f_alternative_exist_v
= f_alternative_exist<T>::value;
#if 0 // enable/disable
template <typename T,
std::enable_if_t<std::rank<T>::value == 1, int> = 0 >
void f (std::ostream & os, T const &)
{
os << "alternative function\n";
os << "rank == 1" << std::endl;
}
#endif
template <typename T,
std::enable_if_t<(std::rank<T>::value > 1)
|| (false == f_alternative_exist_v<T>), int> = 0 >
void f (std::ostream & os, T const &)
{
os << "old function\n";
os << "rank > 1" << std::endl;
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const T& foo)
{
f<T>(os, foo);
return os;
}
int main ()
{
Foo foo1[5];
Foo foo2[5][5];
std::cout << foo1;
std::cout << foo2;
}