我有以下案例可以使用std::enable_if
:
template<typename T,
typename std::enable_if<std::is_same<int, T>::value>::type* = nullptr>
void f() { }
template<typename T,
typename std::enable_if<std::is_same<double, T>::value>::type* = nullptr>
void f() { }
Run Code Online (Sandbox Code Playgroud)
现在,我在cppreference中看到了新的语法,在我看来更加清晰: typename = std::enable_if_t<std::is_same<int, T>::value>>
我想移植我的代码:
template<typename T,
typename = std::enable_if_t<std::is_same<int, T>::value>>
void g() { }
template<typename T,
typename = std::enable_if_t<std::is_same<double, T>::value>>
void g() { }
Run Code Online (Sandbox Code Playgroud)
但现在海湾合作委员会(5.2)抱怨:
error: redefinition of 'template<class T, class> void g()'
void g() { }
Run Code Online (Sandbox Code Playgroud)
为什么会这样 ?如果可能,我该怎么做才能在这种情况下使用新的,更简洁的语法?
在MSVC2017中,这工作正常,两个static_asserts都没有按预期触发:
template <typename T>
struct do_have_size {
template <typename = decltype(std::declval<T>().size())>
static std::true_type check(T);
static std::false_type check(...);
using type = decltype(check(std::declval<T>()));
};
int main() {
using TR = typename do_have_size<std::vector<int>>::type;
using FL = typename do_have_size<int>::type;
static_assert(std::is_same<TR, std::true_type>::value, "TRUE");
static_assert(std::is_same<FL, std::false_type>::value, "FALSE");
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我在g ++ 7.1或clang 4.0中编译,我会得到以下编译器错误:
In instantiation of 'struct do_have_size<int>':
20:39: required from here
9:24: error: request for member 'size' in 'declval<do_have_size<int>::TP>()', which is of non-class type 'int'
Run Code Online (Sandbox Code Playgroud)
根据我对SFINAE的理解,true_type
返回函数的替换应该对int
参数失败,并且应该选择下一个函数,就像在MSVC中一样.为什么clang和g ++根本没有编译它?
我-std=c++17
只用开关编译,可能需要更多东西?
我遇到了关于enable_if和模板特化的适当用法的问题.
修改示例后(出于保密原因),这是一个类似的例子:
我有一个名为"less"的函数,用于检查1st arg是否小于2nd arg.假设我想根据输入的类型有两种不同的实现 - 一个是整数实现,另一个是double.
到目前为止我的代码看起来像这样 -
#include <type_traits>
#include <iostream>
template <class T,
class = typename std::enable_if<std::is_floating_point<T>::value>::type>
bool less(T a, T b) {
// ....
}
template <class T,
class = typename std::enable_if<std::is_integral<T>::value>::type>
bool less(T a, T b) {
// ....
}
int main() {
float a;
float b;
less(a,b);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
上面的代码没有编译,因为 - 它说我正在重新定义less方法.
错误是:
Z.cpp:15:19: error: template parameter redefines default argument
class = typename std::enable_if<std::is_integral<T>::value>::type>
^
Z.cpp:9:19: note: previous default template argument defined here …
Run Code Online (Sandbox Code Playgroud) 这绝对是一个微不足道的问题,但我无法弄清楚如何做到这一点.
我有一个模板功能,比方说template <unsigned int N> void my_function()
.现在,我有两个不同的实现my_function
,第一个应该使用,如果N
大于,比如100,另一个如果N
小于那个.
我试着像这样使用SFINAE:
template <unsigned int N, typename = enable_if <N >= 100> :: type> my_function()
{
// First implementation
}
template <unsigned int N, typename = enable_if <N < 100> :: type> my_function()
{
// Second implementation
}
Run Code Online (Sandbox Code Playgroud)
但那是两次声明相同的功能.然后我尝试做类似的事情
template <unsigned int N, bool = (N >= 100)> my_function();
Run Code Online (Sandbox Code Playgroud)
然后用两个不同的布尔值实现这两个函数.没有成功,因为它是部分专业化.
然后我尝试N
在函数调用中包装为struct参数和bool,但它在专门化类之前专门化了一个成员函数,这是无法完成的.
有合理的方法吗?
比方说,我有六种类型,它们各自属于一个概念类别.
这是一个显示这个的图表:
或者也许是一个更具体的例子:
我想编写两个函数来处理所有6种类型.
"类别1"中的类型以某种方式处理,"类别2"中的类型以不同的方式处理.
让我们进入代码.首先,我将创建六种类型.
//Category 1 Types
class Type_A{};
class Type_B{};
class Type_C{};
//Category 2 Types
class Type_D{};
class Type_E{};
class Type_F{};
Run Code Online (Sandbox Code Playgroud)
接下来,我将创建两个类型特征,以便可以在编译时发现类型的类别.
/* Build The Category 1 Type Trait */
//Type_A Type Trait
template <typename T>
struct Is_Type_A {
static const bool value = false;
};
template <>
struct Is_Type_A<Type_A> {
static const bool value = true;
};
//Type_B Type Trait
template <typename T>
struct Is_Type_B {
static const bool value = false;
};
template <>
struct …
Run Code Online (Sandbox Code Playgroud) 有没有办法只为基本类型制作模板专业化?我试图做以下事情:
template<typename T, typename = typename std::enable_if<!std::is_fundamental<T>::value>::type>
class foo
{
}
template<typename T, typename = typename std::enable_if<std::is_fundamental<T>::value>::type>
class foo
{
}
Run Code Online (Sandbox Code Playgroud)
但我收到一个错误,模板已经定义.
我尝试使用std::enable_if
未使用和未命名的类型参数,以免扭曲return
类型.但是,以下代码无法编译.
#include <iostream>
template <typename T, typename = std::enable_if_t<!std::is_integral<T>::value>>
T foo() { std::cout << "non-integral" << std::endl; return T(); }
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
T foo() { std::cout << "integral" << std::endl; return T(); }
int main() {
foo<float>();
foo<int>();
}
Run Code Online (Sandbox Code Playgroud)
编译器说:
7:3: error: redefinition of 'template<class T, class> T foo()'
4:3: note: 'template<class T, class> T foo()' previously declared here
In function 'int main()':
11:12: error: no matching function for call to 'foo()' …
Run Code Online (Sandbox Code Playgroud) 我有这段代码可以在GCC 9.1中正常工作:
#include <type_traits>
template< typename T >
class A
{
protected:
T value;
public:
template< typename U,
typename...,
typename = std::enable_if_t< std::is_fundamental< U >::value > >
A& operator=(U v)
{
value = v;
return *this;
}
};
template< typename T >
class B : public A<T>
{
public:
using A<T>::operator=;
template< typename U,
typename...,
typename = std::enable_if_t< ! std::is_fundamental< U >::value > >
B& operator=(U v)
{
this->value = v;
return *this;
}
};
int main()
{
B<int> obj; …
Run Code Online (Sandbox Code Playgroud) 我想为值类型为一对的迭代器编写一个专门的模板函数。我的期望是这应该与std :: map的迭代器匹配。
为了检测对:
template <typename>
struct is_pair : std::false_type
{ };
template <typename T, typename U>
struct is_pair<std::pair<T, U>> : std::true_type
{ };
// also tried this, but it didn't help
template <typename T, typename U>
struct is_pair<std::pair<const T, U>> : std::true_type
{ };
Run Code Online (Sandbox Code Playgroud)
然后我在函数声明中使用enable_if:
template<class ITR>
decltype(auto) do_stuff(
std::enable_if<is_pair<typename ITR::value_type>::value, ITR> itr) {
//access of itr->second ok.
}
Run Code Online (Sandbox Code Playgroud)
但是,当我将此功能与地图迭代器一起使用时,我从clang(Xcode 8.3)中收到以下错误消息:
候选模板被忽略:无法将“ enable_if”与“ __map_iterator”匹配
没有进一步的解释,为什么不匹配就启用。
在检查__map_iterator的类型时,看起来它应该与is_pair检查匹配。
我正在尝试为任何可迭代容器编写模板运算符.得到一个奇怪的错误:
#include <iostream>
template <typename C>
std::ostream& operator<<(std::ostream& os, const C& c) {
os << "[";
for (const auto& v : c) {
os << v << " ";
}
os << "]";
return os;
}
Run Code Online (Sandbox Code Playgroud)
vec.cc:5:6:错误:使用重载运算符'<<'是不明确的(操作数类型'std :: ostream'(又名'basic_ostream')和'const char [2]')os <<"[ "; ~~ ^ ~~~
为什么这个错误?我如何实现我想要的目标?