相关疑难解决方法(0)

为什么模板参数中的enable_if_t会抱怨重定义?

我有以下案例可以使用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)

为什么会这样 ?如果可能,我该怎么做才能在这种情况下使用新的,更简洁的语法?

c++ templates sfinae enable-if c++14

29
推荐指数
2
解决办法
2万
查看次数

为什么这个SFINAE片段不能用于g ++,而是在MSVC中工作?

在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只用开关编译,可能需要更多东西?

c++ templates sfinae c++11

19
推荐指数
3
解决办法
1520
查看次数

模板特化和enable_if问题

我遇到了关于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)

c++ templates sfinae enable-if c++11

17
推荐指数
1
解决办法
5886
查看次数

根据模板参数不一致执行不同的功能

这绝对是一个微不足道的问题,但我无法弄清楚如何做到这一点.

我有一个模板功能,比方说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,但它在专门化类之前专门化了一个成员函数,这是无法完成的.

有合理的方法吗?

c++ templates sfinae c++11

14
推荐指数
2
解决办法
3657
查看次数

我可以使用类型特征重载函数吗?

比方说,我有六种类型,它们各自属于一个概念类别.
这是一个显示这个的图表:

类型A,B和C包装在名为


或者也许是一个更具体的例子: Apple,Orange和Banana都是Fruit. 胡萝卜,洋葱和卷心菜都是蔬菜


我想编写两个函数来处理所有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)

c++ templates type-traits template-meta-programming c++11

13
推荐指数
2
解决办法
1321
查看次数

基本类型的模板专业化

有没有办法只为基本类型制作模板专业化?我试图做以下事情:

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)

但我收到一个错误,模板已经定义.

c++ templates metaprogramming generic-programming

7
推荐指数
1
解决办法
428
查看次数

将std :: enable_if与匿名类型参数一起使用

我尝试使用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)

c++ templates sfinae enable-if c++11

6
推荐指数
2
解决办法
640
查看次数

在C ++ 14中继承模板化的operator =:g ++和clang ++的不同行为

我有这段代码可以在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)

c++ language-lawyer overload-resolution name-hiding c++14

5
推荐指数
1
解决办法
145
查看次数

enable_if检查迭代器的值类型是否为一对

我想为值类型为一对的迭代器编写一个专门的模板函数。我的期望是这应该与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检查匹配。

c++ c++11

4
推荐指数
2
解决办法
824
查看次数

为任何载体编写操作符<<的模板

我正在尝试为任何可迭代容器编写模板运算符.得到一个奇怪的错误:

#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 <<"[ "; ~~ ^ ~~~

为什么这个错误?我如何实现我想要的目标?

c++ templates c++11

4
推荐指数
2
解决办法
429
查看次数