1
votes

I have the following code sample ( MSVC 2015 compiled )

https://godbolt.org/g/kccgtb ( for an executable demo )

#include "boost/range/value_type.hpp"

namespace foo { 

    template <typename Range>
    typename boost::range_value<Range>::type
    operator|(Range const& r, int holder)
    {       
    }

}

using namespace foo;


int main(){

}

which under msvc generates the following errors

example.cpp

/opt/compiler-explorer/windows/19.00.24210/include/xlocale(341): warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc

/opt/compiler-explorer/libs/boost_1_67_0\boost/range/value_type.hpp(26): error C2039: 'type': is not a member of 'boost::range_iterator'

    with

    [

        T=unsigned __int64

    ]

/opt/compiler-explorer/libs/boost_1_67_0\boost/range/value_type.hpp(26): note: see declaration of 'boost::range_iterator'

    with

    [

        T=unsigned __int64

    ]

/opt/compiler-explorer/windows/19.00.24210/include/xstring(1659): note: see reference to class template instantiation 'boost::range_value' being compiled

/opt/compiler-explorer/windows/19.00.24210/include/xstring(1658): note: while compiling class template member function 'void std::basic_string,std::allocator>::shrink_to_fit(void)'

/opt/compiler-explorer/windows/19.00.24210/include/system_error(661): note: see reference to function template instantiation 'void std::basic_string,std::allocator>::shrink_to_fit(void)' being compiled

/opt/compiler-explorer/windows/19.00.24210/include/stdexcept(21): note: see reference to class template instantiation 'std::basic_string,std::allocator>' being compiled

/opt/compiler-explorer/libs/boost_1_67_0\boost/range/value_type.hpp(26): error C2146: syntax error: missing '>' before identifier 'type'

/opt/compiler-explorer/libs/boost_1_67_0\boost/iterator/iterator_traits.hpp(23): error C2039: 'value_type': is not a member of 'std::iterator_traits'

    with

    [

        Iterator=int

    ]

/opt/compiler-explorer/libs/boost_1_67_0\boost/iterator/iterator_traits.hpp(23): note: see declaration of 'std::iterator_traits'

    with

    [

        Iterator=int

    ]

/opt/compiler-explorer/libs/boost_1_67_0\boost/range/value_type.hpp(27): note: see reference to class template instantiation 'boost::iterators::iterator_value' being compiled

/opt/compiler-explorer/libs/boost_1_67_0\boost/iterator/iterator_traits.hpp(23): error C3646: 'type': unknown override specifier

/opt/compiler-explorer/libs/boost_1_67_0\boost/iterator/iterator_traits.hpp(23): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

Compiler returned: 2

under gcc and clang it compiles.

See https://godbolt.org/g/kccgtb

2
AFAIK it is a msvc bug. It generally has problem with generic operator| - it tries to match it to internal flags inside stl headers for example (a stumbled upon it once and gave up trying). It is a mess that needs to be worked aroundbartop
@bartop msvc compiles the given code snippet fine when standard conformance mode is enabled.user7860670
@VTT This is strange, but for me it does not, especially taking into account that msvc 2015 does not support C++17.EDIT: latest msvc on godbolt seems not to give compile errors. It's clearly compiler bugbartop

2 Answers

3
votes

One of approaches is to use SFINAE inside template parameters:

template <class Range, class = std::enable_if_t<!std::is_fundamental_v<Range>>>
typename boost::range_value<Range>::type
operator|(
   const Range &r
  , int holder)
{ 
}

It is more concise and less foggy than the one with sfinae argument

1
votes

I have a work around from a work colleauge. It's ugly but seems to work

#include "boost/range/value_type.hpp"

namespace foo { 

    template <typename Range>
    typename boost::range_value<Range>::type
    operator|(
       typename std::enable_if<!std::is_fundamental<Range>::value, Range>::type 
          const& r
      , int holder)
    { 
    }
}

using namespace foo;

int main(){}