相关疑难解决方法(0)

C++,在实现函数`int next(std :: string param)`时出现奇怪的编译器错误

我被以下代码严重咬了,我浪费了很多宝贵的时间.

#include<string>

int next(std::string param){
    return 0;
}

void foo(){
    next(std::string{ "abc" });
}
Run Code Online (Sandbox Code Playgroud)

这会产生以下编译器错误(在Visual Studio 2013上):

1>------ Build started: Project: sandbox, Configuration: Debug Win32 ------
1>  test.cpp
1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\xutility(371): error C2039: 'iterator_category' : is not a member of 'std::basic_string<char,std::char_traits<char>,std::allocator<char>>'
1>          c:\users\ray\dropbox\programming\c++\sandbox\test.cpp(8) : see reference to class template instantiation 'std::iterator_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char>>>' being compiled
1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\xutility(371): error C2146: syntax error : missing ';' before identifier 'iterator_category'
1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\xutility(371): error C4430: …
Run Code Online (Sandbox Code Playgroud)

c++ compiler-errors msvc12

22
推荐指数
3
解决办法
2969
查看次数

SFINAE可以扣除,但不能替代

考虑以下MCVE

struct A {};

template<class T>
void test(T, T) {
}

template<class T>
class Wrapper {
    using type = typename T::type;
};

template<class T>
void test(Wrapper<T>, Wrapper<T>) {
}

int main() {
    A a, b;
    test(a, b);     // works
    test<A>(a, b);  // doesn't work
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这里test(a, b);有效,但test<A>(a, b);失败:

<source>:11:30: error: no type named 'type' in 'A'
    using type = typename T::type;
                 ~~~~~~~~~~~~^~~~
<source>:23:13: note: in instantiation of template class 'Wrap<A>' requested here
    test<A>(a, b); …
Run Code Online (Sandbox Code Playgroud)

c++ templates sfinae language-lawyer c++11

21
推荐指数
2
解决办法
745
查看次数

与SFINAE中的硬错误混淆

关于以下代码(https://wandbox.org/permlink/nhx4pheijpTF1ohf为方便起见,下面转载)

#include <type_traits>
#include <utility>

namespace foo_name {
template <typename T>
void foo();
template <>
void foo<int>();

template <typename T>
struct c_size;
template <>
struct c_size<int> : public std::integral_constant<int, 1> {};
} // namespace foo_name

template <typename Type>
class Foo {
public:
    template <typename T>
    static decltype(auto) impl(T&& t) {
        using foo_name::foo;
        return foo(std::forward<T>(t));
    }
};

class Something {};

template <typename Type, typename T = std::decay_t<Type>>
using EnableIfHasFoo = std::void_t<
    decltype(Foo<T>::impl(std::declval<T>())),
    decltype(foo_name::c_size<Type>::value)>;

template <typename Type, typename = std::void_t<>> …
Run Code Online (Sandbox Code Playgroud)

c++ templates sfinae c++17

15
推荐指数
1
解决办法
366
查看次数

静态断言和SFINAE

考虑一下:

template <typename T>
struct hash
{
     static_assert(false,"Not implemented.");
};

struct unhashable {};

template <typename T>
auto test(const T &t) -> decltype((*(hash<T> const *)nullptr)(t),int);

void test(...);

int main()
{
    std::cout << std::is_same<decltype(test(std::declval<unhashable>())),void>::value;
}
Run Code Online (Sandbox Code Playgroud)

除了显然缺少标题,这应该编译吗?

换句话说,我问的是,如果在推断重载函数模板的返回值的同时触发尾随decltype内部的静态断言失败是否要求停止编译,或者是否只是丢弃了重载.

在gcc 4.7上,编译失败.我很积极,虽然这将在gcc 4.8中编译好(但在此刻无法检查).谁是对的?

c++ static-assert sfinae c++11

10
推荐指数
2
解决办法
2732
查看次数

如何使用SFINAE创建相同方法的2种不同实现

我已经阅读了一些关于SFINAE的文章,但找不到我的案例的解决方案.这就是我想要做的事情:

#include <type_traits>

struct CByteArray {};
struct HLVariant {
    HLVariant() {}
    HLVariant(const HLVariant&) {}
    HLVariant(const CByteArray&) {}

    };

template <typename T>
struct Serializer
{
    static inline typename std::enable_if<std::is_pod<T>::value, CByteArray>::type serialize(const T& value)
    {
        static_assert(std::is_pod<T>::value, "Not a POD type");
        return CByteArray();
    }

    static inline typename std::enable_if<!std::is_pod<T>::value, CByteArray>::type serialize(const T& value)
    {
        return Serializer<HLVariant>::serialize(HLVariant(value));
    }
};

template <>
struct Serializer<HLVariant>
{
    static inline CByteArray serialize(const HLVariant& value)
    {
        return CByteArray();
    }
};

int main()
{
    int i = 0;
    Serializer<int>::serialize(i);
    Serializer<CByteArray>::serialize(CByteArray());
    Serializer<HLVariant>::serialize(HLVariant()); …
Run Code Online (Sandbox Code Playgroud)

c++ templates sfinae c++11

8
推荐指数
1
解决办法
1040
查看次数

is_constructible和is_destructible不受朋友声明的影响

friend在评估std::is_constructible和评估时,Clang和GCC似乎不尊重声明std::is_destructible.

关于`is_constructible,cppreference.com说:

从与T无关的上下文和Args中的任何类型执行访问检查.仅考虑变量定义的直接上下文的有效性.

(该网站没有解释如何is_destructible处理访问检查,但访问修饰符确实会影响is_destructible一般的行为,所以我希望它的工作方式与之相同is_constructible.)

因此,在我看来,这个代码应该编译,因为在直接背景检查构造函数和析构函数都是可用的,由当地变量实例为证:

class Private
{
    Private() {}
    ~Private() {}

    friend class Friend;
};

class Friend
{
    public:
        Friend()
        {
            // Both of these should fire, but they do not.
            static_assert(
                !std::is_constructible<Private>::value,
                "the constructor is public");
            static_assert(
                !std::is_destructible<Private>::value,
                "the destructor is public");
            // There is no error here.
            Private p;
        }
};
Run Code Online (Sandbox Code Playgroud)

...但Coliru编译它没有错误(使用GCC或Clang).

这是两个编译器中的错误(或至少是不合格),或者cppreference.com是否歪曲了标准,还是我误解了cppreference.com的声明?

c++ gcc access-modifiers clang c++11

8
推荐指数
1
解决办法
148
查看次数

为什么具有无效继承的类型不会通过 void_t 获得 SFINAE-out?

假设我们有一个当前类:

template<typename T>
struct Inheriter : public T {};
Run Code Online (Sandbox Code Playgroud)

T请注意,仅当/未声明为时class,其实例化才是格式正确的。structfinal

然后,借助 SFINAE 的强大功能,std::void_t我们可以在编译时检查类型是格式良好还是格式错误。让我们用它来编写我们自己的简单实现std::is_final

template<typename T, typename = void>
struct IsFinal : public std::true_type{};

template<typename T>
struct IsFinal<T, std::void_t<decltype(Inheriter<T>{})>> : public std::false_type{};
Run Code Online (Sandbox Code Playgroud)

对于任何任意类型,T编译器都应该实例化最专业的版本IsFinal,如果替换失败,则尝试实例化最不专业的版本。并且只有当所有这些都失败时,编译器才必须吐出错误。

但是在 Clang 14 和 GCC 11.2(目前最新的)上,当我们将某种final类型作为模板参数传递给时IsFinal,我们会收到编译错误(https://godbolt.org/z/q8jxP3Thc)。

为什么编译器不尝试实例化最不专业的版本IsFinal,并直接吐出错误?这是编译器错误还是 C++ 语言标准的某些棘手部分?

c++ metaprogramming sfinae language-lawyer template-meta-programming

7
推荐指数
0
解决办法
137
查看次数

SFINAE,演绎与实例化

这段代码无法在大多数编译器中编译,但起初我直观地期望SFINAE保护我:

typedef void (*A)();

template < typename T >
struct a_metafun { typedef typename T::type type; };

template < typename T >
typename a_metafun<T>::type f(T) {}

template < typename T>
void f(T(*)()) {}

int main() { f(A()); }
Run Code Online (Sandbox Code Playgroud)

我可以通过至少两种方式解决问题:

1)将"metafun"f()的定义更改为:

template < typename T > typename T::type f(T) {}

2)定义"a_metafun",使得它分析T并且如果T有一个则有一个类型,如果没有则不具有...但是在没有错误的情况下实例化:

BOOST_MPL_HAS_XXX_TRAIT_DEF(type)

typedef < template T, bool = has_type<T>::value >
struct a_metafun { };

typedef < template T >
struct a_metafun<T, true> { typedef typename T::type type };
Run Code Online (Sandbox Code Playgroud)

在查看14.8.2(C++ 03)时,我认为它确切地说明了SFINAE可以应用的条件.有没有更好的地方看?在已经推断出的模板的实例化中失败,即使在扣除另一个模板时,也不会包含在此列表中.

我用来解释造成这种非法行为的另一个方向是,a_metafun的演绎已经发生,其内部的实例化是导致错误的原因.SFINAE在实例化期间不适用,但仅在扣除期间适用,或者我错在那里?但是在第二种情况下,a_metafun正确,并且格式良好地实例化,但它内部没有"类型"定义,这意味着试图实例化它的模板由于替换而失败. …

c++ standards

6
推荐指数
1
解决办法
373
查看次数

为什么编译器说:'enable_if'不能用于禁用此声明

template <bool Cond, typename Type = void>
using Enable_if = typename std::enable_if<Cond, Type>::type;

class Degree;

template <typename T>
constexpr inline bool Is_Degree() {
    return std::is_base_of<Degree, T>::value;
}

class Degree {
public:
    std::size_t inDeg = 0;
};

template <typename Satellite = Degree>
class Vertex: public Satellite {
public:
    explicit Vertex(int num): n(num) {}
private:
    std::size_t n;
};

template <typename Satellite = Degree>
class Edge {
public:
    // i want have different constructor depending on 
    // whether Vertex is (directly or indirectly) …
Run Code Online (Sandbox Code Playgroud)

c++ enable-if

6
推荐指数
1
解决办法
1468
查看次数

正确使用std :: enable_if的方法

这些类之间有什么区别?这些方法与enable_if完全一样。

/// Alias of std::enable_if...
template <bool B, typename T = void>
using Enable_if = typename std::enable_if<B, T>::type;

Template<typename T, std::size_t N>
class A {
   ...
    template <std::size_t NN = N,
          typename = Enable_if<NN == 2>>
    Some_Return_Type
    method(param1, param2)
    {}

    template <std::size_t NN = N,
              typename = Enable_if<NN == 1>>
    Some_Return_Type
    method(param1)
    {}


};


Template<typename T, std::size_t N>
class B {
   ...
    Enable_if<N == 2, Some_Return_Type>
    method(param1, param2)
    {}

    Enable_if<N == 1, Some_Return_Type>
    method(param1)
    {}
};
Run Code Online (Sandbox Code Playgroud)

在以下情况下,使用enable_if的正确方法是什么:

  • 至少2个仅在参数上有所不同且名称相同的方法,但只有一个必须是“活动的”(如果N == 1,则其中一个,如果N …

c++ c++11

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