Opened 7 years ago

Closed 7 years ago

Last modified 6 years ago

#11897 closed Bugs (fixed)

Compile failure in type_traits_detail::mp_valid_impl with CUDA 7.0

Reported by: a.grund@… Owned by: John Maddock
Milestone: Boost 1.63.0 Component: type_traits
Version: Boost 1.60.0 Severity: Showstopper
Keywords: Cc:

Description

Including boost/thread/pthread/timespec.hpp and compiling with nvcc 7.0 in C++11 mode throws several errors related to mp_valid_impl. This bug seems to be a compiler bug which is fixed in CUDA 7.5 but as many HPC system only have (and will have) 7.0 this is a real showstopper. Log output is:

/opt/pkg/devel/cuda/7.0/bin/nvcc -std=c++11 BoostMpValid.cu
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/type_traits/detail/mp_defer.hpp(33): error: no instance of overloaded function "boost::type_traits_detail::mp_valid_impl<F, T...>::check [with F=boost::type_traits_detail::common_type_fold, T=<int_least64_t, int_least64_t, intmax_t>]" matches the argument list
            argument types are: (int)
          detected during:
            instantiation of class "boost::type_traits_detail::mp_valid_impl<F, T...> [with F=boost::type_traits_detail::common_type_fold, T=<int_least64_t, int_least64_t, intmax_t>]" 
(37): here
            instantiation of type "boost::type_traits_detail::mp_valid<boost::type_traits_detail::common_type_fold, int_least64_t, int_least64_t, intmax_t>" 
(50): here
            instantiation of type "boost::type_traits_detail::mp_defer<boost::type_traits_detail::common_type_fold, int_least64_t, int_least64_t, intmax_t>" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/type_traits/common_type.hpp(47): here
            instantiation of class "boost::common_type<T1, T2, T...> [with T1=int_least64_t, T2=int_least64_t, T=<intmax_t>]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/chrono/duration.hpp(256): here
            instantiation of "ToDuration boost::chrono::detail::duration_cast_aux<FromDuration, ToDuration, Period, true, false>::operator()(const FromDuration &) const [with FromDuration=boost::chrono::duration<int_least64_t, boost::nano>, ToDuration=boost::chrono::seconds, Period=boost::ratio<1L, 1000000000L>]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/chrono/duration.hpp(315): here
            instantiation of "ToDuration boost::chrono::detail::duration_cast<FromDuration, ToDuration>::operator()(const FromDuration &) const [with FromDuration=boost::chrono::duration<int_least64_t, boost::nano>, ToDuration=boost::chrono::seconds]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/chrono/duration.hpp(789): here
            instantiation of "boost::enable_if<boost::chrono::detail::is_duration<ToDuration>, ToDuration>::type boost::chrono::duration_cast<ToDuration,Rep,Period>(const boost::chrono::duration<Rep, Period> &) [with ToDuration=boost::chrono::seconds, Rep=int_least64_t, Period=boost::nano]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/thread/pthread/timespec.hpp(51): here

/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/type_traits/detail/mp_defer.hpp(50): error: name followed by "::" must be a class or namespace name
          detected during:
            instantiation of type "boost::type_traits_detail::mp_defer<boost::type_traits_detail::common_type_fold, int_least64_t, int_least64_t, intmax_t>" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/type_traits/common_type.hpp(47): here
            instantiation of class "boost::common_type<T1, T2, T...> [with T1=int_least64_t, T2=int_least64_t, T=<intmax_t>]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/chrono/duration.hpp(256): here
            instantiation of "ToDuration boost::chrono::detail::duration_cast_aux<FromDuration, ToDuration, Period, true, false>::operator()(const FromDuration &) const [with FromDuration=boost::chrono::duration<int_least64_t, boost::nano>, ToDuration=boost::chrono::seconds, Period=boost::ratio<1L, 1000000000L>]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/chrono/duration.hpp(315): here
            instantiation of "ToDuration boost::chrono::detail::duration_cast<FromDuration, ToDuration>::operator()(const FromDuration &) const [with FromDuration=boost::chrono::duration<int_least64_t, boost::nano>, ToDuration=boost::chrono::seconds]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/chrono/duration.hpp(789): here
            instantiation of "boost::enable_if<boost::chrono::detail::is_duration<ToDuration>, ToDuration>::type boost::chrono::duration_cast<ToDuration,Rep,Period>(const boost::chrono::duration<Rep, Period> &) [with ToDuration=boost::chrono::seconds, Rep=int_least64_t, Period=boost::nano]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/thread/pthread/timespec.hpp(51): here

/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/type_traits/detail/mp_defer.hpp(33): error: no instance of overloaded function "boost::type_traits_detail::mp_valid_impl<F, T...>::check [with F=boost::type_traits_detail::builtin_common_type, T=<int_least64_t, int_least64_t>]" matches the argument list
            argument types are: (int)
          detected during:
            instantiation of class "boost::type_traits_detail::mp_valid_impl<F, T...> [with F=boost::type_traits_detail::builtin_common_type, T=<int_least64_t, int_least64_t>]" 
(37): here
            instantiation of type "boost::type_traits_detail::mp_valid<boost::type_traits_detail::builtin_common_type, int_least64_t, int_least64_t>" 
(50): here
            instantiation of type "boost::type_traits_detail::mp_defer<boost::type_traits_detail::builtin_common_type, int_least64_t, int_least64_t>" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/type_traits/common_type.hpp(96): here
            instantiation of class "boost::type_traits_detail::common_type_impl<T1, T2> [with T1=int_least64_t, T2=int_least64_t]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/type_traits/common_type.hpp(132): here
            instantiation of class "boost::type_traits_detail::common_type_decay_helper<T1, T2, T1, T2> [with T1=int_least64_t, T2=int_least64_t]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/type_traits/common_type.hpp(138): here
            [ 3 instantiation contexts not shown ]
            instantiation of class "boost::type_traits_detail::mp_defer_impl<F, T...> [with F=boost::type_traits_detail::common_type_fold, T=<int_least64_t, int_least64_t, intmax_t>]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/type_traits/common_type.hpp(47): here
            instantiation of class "boost::common_type<T1, T2, T...> [with T1=int_least64_t, T2=int_least64_t, T=<intmax_t>]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/chrono/duration.hpp(256): here
            instantiation of "ToDuration boost::chrono::detail::duration_cast_aux<FromDuration, ToDuration, Period, true, false>::operator()(const FromDuration &) const [with FromDuration=boost::chrono::duration<int_least64_t, boost::nano>, ToDuration=boost::chrono::seconds, Period=boost::ratio<1L, 1000000000L>]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/chrono/duration.hpp(315): here
            instantiation of "ToDuration boost::chrono::detail::duration_cast<FromDuration, ToDuration>::operator()(const FromDuration &) const [with FromDuration=boost::chrono::duration<int_least64_t, boost::nano>, ToDuration=boost::chrono::seconds]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/chrono/duration.hpp(789): here
            instantiation of "boost::enable_if<boost::chrono::detail::is_duration<ToDuration>, ToDuration>::type boost::chrono::duration_cast<ToDuration,Rep,Period>(const boost::chrono::duration<Rep, Period> &) [with ToDuration=boost::chrono::seconds, Rep=int_least64_t, Period=boost::nano]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/thread/pthread/timespec.hpp(51): here

/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/type_traits/detail/mp_defer.hpp(50): error: name followed by "::" must be a class or namespace name
          detected during:
            instantiation of type "boost::type_traits_detail::mp_defer<boost::type_traits_detail::builtin_common_type, int_least64_t, int_least64_t>" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/type_traits/common_type.hpp(96): here
            instantiation of class "boost::type_traits_detail::common_type_impl<T1, T2> [with T1=int_least64_t, T2=int_least64_t]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/type_traits/common_type.hpp(132): here
            instantiation of class "boost::type_traits_detail::common_type_decay_helper<T1, T2, T1, T2> [with T1=int_least64_t, T2=int_least64_t]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/type_traits/common_type.hpp(138): here
            instantiation of class "boost::common_type<T1, T2> [with T1=int_least64_t, T2=int_least64_t]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/type_traits/common_type.hpp(37): here
            instantiation of type "boost::common_type_t<int_least64_t, int_least64_t>" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/type_traits/common_type.hpp(42): here
            instantiation of type "boost::type_traits_detail::common_type_fold<int_least64_t, int_least64_t, intmax_t>" 
(47): here
            instantiation of class "boost::type_traits_detail::mp_defer_impl<F, T...> [with F=boost::type_traits_detail::common_type_fold, T=<int_least64_t, int_least64_t, intmax_t>]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/type_traits/common_type.hpp(47): here
            instantiation of class "boost::common_type<T1, T2, T...> [with T1=int_least64_t, T2=int_least64_t, T=<intmax_t>]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/chrono/duration.hpp(256): here
            instantiation of "ToDuration boost::chrono::detail::duration_cast_aux<FromDuration, ToDuration, Period, true, false>::operator()(const FromDuration &) const [with FromDuration=boost::chrono::duration<int_least64_t, boost::nano>, ToDuration=boost::chrono::seconds, Period=boost::ratio<1L, 1000000000L>]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/chrono/duration.hpp(315): here
            instantiation of "ToDuration boost::chrono::detail::duration_cast<FromDuration, ToDuration>::operator()(const FromDuration &) const [with FromDuration=boost::chrono::duration<int_least64_t, boost::nano>, ToDuration=boost::chrono::seconds]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/chrono/duration.hpp(789): here
            instantiation of "boost::enable_if<boost::chrono::detail::is_duration<ToDuration>, ToDuration>::type boost::chrono::duration_cast<ToDuration,Rep,Period>(const boost::chrono::duration<Rep, Period> &) [with ToDuration=boost::chrono::seconds, Rep=int_least64_t, Period=boost::nano]" 
/opt/pkg/devel/boost/1.60.0/gnu/4.8.2/64/opt/include/boost/thread/pthread/timespec.hpp(51): here

I have reduced it to the following MWE which gives the same error (CUDA 7.0, Boost 1.60):

#include <boost/type_traits/common_type.hpp>
#include <cstdint>

int main(){
    boost::common_type<int_least64_t, int_least64_t, intmax_t>::type i;
}

Change History (22)

comment:1 by Alex Grund <a.grund@…>, 7 years ago

This bug was introduced in 1.60. 1.59 is working fine. As the following code shows, the problem is related to variadic templates:

#include <type_traits>

template<template<class...> class F, class... T>
struct mp_valid_impl
{
    template<template<class...> class G, class = G<T...>>
    static int check(int);

    template<template<class...> class>
    static bool check(...);

    using type = decltype(check<F>(0));
};

template<template<class...> class F, class T>
struct mp_valid_impl2
{
    template<template<class...> class G, class = G<T>>
    static int check(int);

    template<template<class...> class>
    static bool check(...);

    using type = decltype(check<F>(0));
};

template<template<class> class F, class T>
struct mp_valid_impl3
{
    template<template<class> class G, class = G<T>>
    static int check(int);

    template<template<class> class>
    static bool check(...);

    using type = decltype(check<F>(0));
};


template<typename T>
struct MetaFunc{};

int main(){
    typename mp_valid_impl<MetaFunc, int>::type i;
    typename mp_valid_impl2<MetaFunc, int>::type i2;
    typename mp_valid_impl3<MetaFunc, int>::type i3;
}

Output:

BoostMpValid.cu(12): error: no instance of overloaded function "mp_valid_impl<F, T...>::check [with F=MetaFunc, T=<int>]" matches the argument list
            argument types are: (int)
          detected during instantiation of class "mp_valid_impl<F, T...> [with F=MetaFunc, T=<int>]" 
(44): here

BoostMpValid.cu(24): error: no instance of overloaded function "mp_valid_impl2<F, T>::check [with F=MetaFunc, T=int]" matches the argument list
            argument types are: (int)
          detected during instantiation of class "mp_valid_impl2<F, T> [with F=MetaFunc, T=int]" 
(45): here

BoostMpValid.cu(46): warning: variable "i3" was declared but never referenced

So only the non-variadic version works. A simple workaround is probably to deactivate variadic templates by defining BOOST_NO_CXX11_VARIADIC_TEMPLATES for nvcc < 7.5. 7.5 is working so this can be used there.

comment:2 by Alex Grund <a.grund@…>, 7 years ago

Possible workaround: Add the following to the end of config/compiler/nvcc.hpp;

// A bug in version 7.0 of CUDA prevents use of variadic templates in some occasions
// https://svn.boost.org/trac/boost/ticket/11897
// This is fixed in 7.5. As the following version macro was introduced in 7.5 an existance
// check is enough to detect versions < 7.5
#ifndef __CUDACC_VER__
#   define BOOST_NO_CXX11_VARIADIC_TEMPLATES
#endif

comment:3 by John Maddock, 7 years ago

Many thanks for investigating this so thoroughly. My only worry about setting BOOST_NO_CXX11_VARIADIC_TEMPLATES as a workaround, is that it may disable otherwise working code in other library interfaces. Does the patch below fix things?

index 5c4303b..4a26d92 100644
--- a/include/boost/type_traits/common_type.hpp
+++ b/include/boost/type_traits/common_type.hpp
@@ -12,12 +12,13 @@
 #include <boost/config.hpp>
 #include <boost/type_traits/decay.hpp>
 #include <boost/type_traits/declval.hpp>
+#include <boost/detail/workaround.hpp>

 #if defined(BOOST_NO_CXX11_DECLTYPE)
 #include <boost/type_traits/detail/common_type_impl.hpp>
 #endif

-#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !BOOST_WORKAROUND(__CUDACC_VER__,  < 70500)
 #include <boost/type_traits/detail/mp_defer.hpp>
 #endif

@@ -26,7 +27,7 @@ namespace boost

 // variadic common_type

-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !BOOST_WORKAROUND(__CUDACC_VER__,  < 70500)

 template<class... T> struct common_type
 {

comment:4 by Alex Grund <a.grund@…>, 7 years ago

I was proposing to disable this as this is 1 case where variadic templates fail in NVCC 7.0 so I would not rely on its correctness and avoid it.

The proposed patch of yours does not work for 2 reasons: 1) You forgot one #if on line 89 2) The symbol is undefined in 7.0 and prior. Due to the check in BOOST_WORKAROUND for the existance and !=0 of the symbol it will always yield false. I don't see a good way to use that macro here. Using the plain defined(...) or ...>=70500 works.

comment:5 by Alex Grund <a.grund@…>, 7 years ago

Note that there is already a check in that form: #if !defined(BOOST_MSVC)
BOOST_MSVC > 1800

So using the >= would probably be ok

comment:6 by a.huebl@…, 7 years ago

Careful with BOOST_WORKAROUND(__CUDACC_VER__, < 70500) please, __CUDACC_VER__ is first defined in CUDA 7.5 and will evaluate to undefined in previous versions. I guess BOOST_WORKAROUND will not evaluate to true in such a case.

comment:7 by anonymous, 7 years ago

Careful with BOOST_WORKAROUND(CUDACC_VER, < 70500) please, CUDACC_VER is first defined in CUDA 7.5 and will evaluate to undefined in previous versions. I guess BOOST_WORKAROUND will not evaluate to true in such a case.

That's what we want - when CUDACC_VER is not defined it evaluates as 0 when used in a conditional (std mandated behaviour). So if CUDACC_VER is either undefined or less than the specified version then !BOOST_WORKAROUND(CUDACC_VER, < 70500) is false and the variadic template branch is not taken.

So 2 questions:

1) Is there any evidence that variadic template support is causing issues elsewhere in Boost?

2) If I update the patch as below, can someone please test it it?

index c887a89..2b85a39 100644
--- a/include/boost/type_traits/common_type.hpp
+++ b/include/boost/type_traits/common_type.hpp
@@ -18,7 +18,7 @@
 #include <boost/type_traits/detail/common_type_impl.hpp>
 #endif

-#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !BOOST_WORKAROUND(__CUDACC_VER__,  < 70500)
 #include <boost/type_traits/detail/mp_defer.hpp>
 #endif

@@ -27,7 +27,7 @@ namespace boost

 // variadic common_type

-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !BOOST_WORKAROUND(__CUDACC_VER__,  < 70500)

 template<class... T> struct common_type
 {
@@ -86,7 +86,7 @@ namespace type_traits_detail

 #if !defined(BOOST_NO_CXX11_DECLTYPE)

-#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !BOOST_WORKAROUND(__CUDACC_VER__,  < 70500)

 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1800

comment:8 by Alex Grund <a.grund@…>, 7 years ago

Yes, but the implementation of BOOST_WORKAROUND is:

#  define BOOST_WORKAROUND(symbol, test)                \
         ((symbol ## _WORKAROUND_GUARD + 0 == 0) &&     \
         (symbol != 0) && (1 % (( (symbol test) ) + 1)))

There is a check if that symbol evaluates to 0 causing the failure I described above. This is why BOOST_WORKAROUND cannot be used for this!

So:
1) Currently not. But similar uses of variadic templates will probably fail. Currently nothing else uses mp_defer (1.60) but other code in future versions may use that as well and run into the same bug.
2) No because BOOST_WORKAROUND always evaluates to false for this. Prior to 7.5 the symbol is undefined causing the (symbol != 0) check to fail, and in >=7.5 the 2nd part of the check will fail.

comment:9 by John Maddock, 7 years ago

Resolution: fixed
Status: newclosed

OK, I've changed Boost.Config.

Please see https://github.com/boostorg/config/commit/2090da494ebe0bd79997234a9733191eac425564 and verify that this works for you.

comment:10 by Alex Grund <a.grund@…>, 7 years ago

Tested with CUDA 7.0 and 7.5 and verified that this works

Thanks for including the fix

comment:11 by sharvil, 7 years ago

Apple LLVM version 7.0.2 (clang-700.1.81) is also affected by this.

comment:12 by John Maddock, 7 years ago

Apple LLVM version 7.0.2 (clang-700.1.81) is also affected by this.

Can you be more specific? Do you mean nvcc on top of clang or just regular clang as shipped by Apple?

in reply to:  12 ; comment:13 by sharvil, 7 years ago

Replying to johnmaddock:

Apple LLVM version 7.0.2 (clang-700.1.81) is also affected by this.

Can you be more specific? Do you mean nvcc on top of clang or just regular clang as shipped by Apple?

Just regular clang as shipped by Apple.

in reply to:  13 comment:14 by Michel Morin, 7 years ago

Just regular clang as shipped by Apple.

With OP's test case, I was not able to reproduce the error on Apple Clang. Do you have a test case?

Thanks.

$ clang++ --version
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.2.0
Thread model: posix
$ clang++ -std=c++11 -I boost_1_60_0/ -xc++ -
#include <boost/type_traits/common_type.hpp>
#include <cstdint>

int main(){
    boost::common_type<int_least64_t, int_least64_t, intmax_t>::type i;
}
$ echo $?
0

comment:15 by anonymous, 7 years ago

Regression tests for Clang version 7.0.2 (clang-700.1.81) all seem to be passing as well...

comment:16 by sharvil, 7 years ago

Yeah, that test case does work. I'll try to extract the minimum piece of code that triggers this from our project over the weekend. But, we did manage to unblock our builds by disabling variadic templates.

comment:17 by antar1nd, 7 years ago

On OSX, it can be reproduced if you compile it for objective-c++ .

#import <Foundation/Foundation.h>
#include <boost/type_traits/common_type.hpp>

int main(int argc, const char * argv[]) {
    boost::common_type<int_least64_t, int_least64_t, intmax_t>::type i;
    return 0;
}

Compiling the above results in :

$ clang++ -std=c++11 -I boost_1_60_0/ -ObjC++ test.mm
In file included from test.mm:2:
In file included from boost_1_60_0/boost/type_traits/common_type.hpp:21:
boost_1_60_0/boost/type_traits/detail/mp_defer.hpp:28:5: warning: declaration does not declare anything [-Wmissing-declarations]
    static boost::true_type check(int);
    ^~~~~~~~~~~~~~~~~~~~~~~
boost_1_60_0/boost/type_traits/detail/mp_defer.hpp:31:5: warning: declaration does not declare anything [-Wmissing-declarations]
    static boost::false_type check(...);
    ^~~~~~~~~~~~~~~~~~~~~~~~
boost_1_60_0/boost/type_traits/detail/mp_defer.hpp:33:27: error: use of undeclared identifier 'check'
    using type = decltype(check<F>(0));
                          ^
boost_1_60_0/boost/type_traits/detail/mp_defer.hpp:33:33: error: cannot refer to class template 'F' without a template argument list
    using type = decltype(check<F>(0));
                                ^
boost_1_60_0/boost/type_traits/detail/mp_defer.hpp:24:35: note: template is declared here
template<template<class...> class F, class... T>
                                  ^
boost_1_60_0/boost/type_traits/detail/mp_defer.hpp:37:1: error: no type named 'type' in 'boost::type_traits_detail::mp_valid_impl<common_type_fold, long long, long long, long>'
using mp_valid = typename mp_valid_impl<F, T...>::type;
^~~~~
boost_1_60_0/boost/type_traits/detail/mp_defer.hpp:50:95: note: in instantiation of template type alias 'mp_valid' requested here
template<template<class...> class F, class... T> using mp_defer = typename boost::conditional<mp_valid<F, T...>::value, mp_defer_impl<F, T...>, mp_empty>::type;
                                                                                              ^
boost_1_60_0/boost/type_traits/common_type.hpp:47:55: note: in instantiation of template type alias 'mp_defer' requested here
struct common_type<T1, T2, T...>: type_traits_detail::mp_defer<type_traits_detail::common_type_fold, T1, T2, T...>
                                                      ^
test.mm:5:9: note: in instantiation of template class 'boost::common_type<long long, long long, long>' requested here
        boost::common_type<int_least64_t, int_least64_t, intmax_t>::type i;
               ^
2 warnings and 3 errors generated.

The root cause is the expansion of a macro "check" defined in the OSX_SDK_10.11's AssertMacros.h . Defining either BOOST_NO_CXX11_TEMPLATE_ALIASES or BOOST_NO_CXX11_VARIADIC_TEMPLATES excludes mp_defer.hpp therefore that works as a workaround. What also works is #undef check before this inclusion.

comment:19 by John Maddock, 7 years ago

The check macro issue is presumably a whole different issue, but if not then yes, this should be fixed in the next release.

comment:20 by bchretien, 6 years ago

Apparently the bug is back with CUDA 8.0 (tested with Boost 1.61.0). With the original repro code:

$ /usr/local/cuda-7.5/bin/nvcc bug.cu -std=c++11
// No issue

$ /usr/local/cuda-8.0/bin/nvcc bug.cu -std=c++11
error: class "boost::common_type<int_least64_t, int_least64_t, intmax_t>" has no member "type"

comment:21 by John Maddock, 6 years ago

Milestone: To Be DeterminedBoost 1.63.0

You're right - CUDA 8 has the same issue! I've just pushed some changes to Boost.Config develop to fix this.

in reply to:  21 comment:22 by bchretien, 6 years ago

I forwarded the issue to the NVIDIA developers, they fixed the problem for the next CUDA release.

Note: See TracTickets for help on using tickets.