Is it possible to static_assert that a lambda is not generic?Can we get the type of a lambda argument?Is it possible to write a template to check for a function's existence?What is a lambda expression in C++11?Compiling with gcc fails if using lambda function for QObject::connect()c++11 - getting result_of, decltype, std::function and variadic templates working togetherTemplate Type Deduction with LambdasVariadic template method and std::function - compilation errorRecursively visiting an `std::variant` using lambdas and fixed-point combinatorsClang can't find template binary operator in fold expressionGenerating lambda from class templateGetting active value in std::visit without knowing which value is active

Replacing matching entries in one column of a file by another column from a different file

Why doesn't Newton's third law mean a person bounces back to where they started when they hit the ground?

Revoked SSL certificate

How does quantile regression compare to logistic regression with the variable split at the quantile?

Was any UN Security Council vote triple-vetoed?

If human space travel is limited by the G force vulnerability, is there a way to counter G forces?

Why can't I see bouncing of a switch on an oscilloscope?

Is it possible to do 50 km distance without any previous training?

What defenses are there against being summoned by the Gate spell?

What does the "remote control" for a QF-4 look like?

A newer friend of my brother's gave him a load of baseball cards that are supposedly extremely valuable. Is this a scam?

Modeling an IP Address

Are the number of citations and number of published articles the most important criteria for a tenure promotion?

RSA: Danger of using p to create q

Intersection point of 2 lines defined by 2 points each

dbcc cleantable batch size explanation

Could an aircraft fly or hover using only jets of compressed air?

Why can't we play rap on piano?

How does one intimidate enemies without having the capacity for violence?

LaTeX: Why are digits allowed in environments, but forbidden in commands?

I'm flying to France today and my passport expires in less than 2 months

Did Shadowfax go to Valinor?

Why is 150k or 200k jobs considered good when there's 300k+ births a month?

infared filters v nd



Is it possible to static_assert that a lambda is not generic?


Can we get the type of a lambda argument?Is it possible to write a template to check for a function's existence?What is a lambda expression in C++11?Compiling with gcc fails if using lambda function for QObject::connect()c++11 - getting result_of, decltype, std::function and variadic templates working togetherTemplate Type Deduction with LambdasVariadic template method and std::function - compilation errorRecursively visiting an `std::variant` using lambdas and fixed-point combinatorsClang can't find template binary operator in fold expressionGenerating lambda from class templateGetting active value in std::visit without knowing which value is active






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








10















I implemented a Visit function (on a variant) that checks that the currently active type in the variant matches the function signature (more precisely the first argument). Based on this nice answer.
For example



#include <variant>
#include <string>
#include <iostream>

template<typename Ret, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(*) (Arg, Rest...));

template<typename Ret, typename F, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(F::*) (Arg, Rest...));

template<typename Ret, typename F, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(F::*) (Arg, Rest...) const);

template <typename F>
decltype(first_argument_helper(&F::operator())) first_argument_helper(F);

template <typename T>
using first_argument = decltype(first_argument_helper(std::declval<T>()));

std::variant<int, std::string> data="abc";
template <typename V>
void Visit(V v)
using Arg1 = typename std::remove_const_t<std::remove_reference_t<first_argument<V>>>;//... TMP magic to get 1st argument of visitor + remove cvr, see Q 43526647
if (! std::holds_alternative<Arg1>(data))
std::cerr<< "alternative mismatchn";
return;

v(std::get<Arg1>(data));

int main()
Visit([](const int& i)std::cout << i << "n"; );
Visit([](const std::string& s)std::cout << s << "n"; );
// Visit([](auto& x)); ugly kabooom



This works, but it explodes with a user unfriendly compile time error when users passes a generic (e.g. [](auto&)) lambda. Is there a way to detect this and give nice static_assert() about it?
Would also be nice if it worked with function templates as well, not just with lambdas.



Note that I do not know what possible lambdas do, so I can not do some clever stuff with Dummy types since lambdas may invoke arbitrary functions on types.
In other words I can not try to call lambda in 2 std::void_t tests on int and std::string and if it works assume it is generic because they might try to call .BlaLol() on int and string.










share|improve this question



















  • 1





    What if the functor has an overloaded operator()? Visiting is also very commonly performed with overloaded functors (see example 4 here), do those have to be forbidden (or have to work)?

    – Max Langhof
    2 days ago












  • I think that is too hard to handle, but if it can be done that would be nice... so it is optional, not required.

    – NoSenseEtAl
    2 days ago

















10















I implemented a Visit function (on a variant) that checks that the currently active type in the variant matches the function signature (more precisely the first argument). Based on this nice answer.
For example



#include <variant>
#include <string>
#include <iostream>

template<typename Ret, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(*) (Arg, Rest...));

template<typename Ret, typename F, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(F::*) (Arg, Rest...));

template<typename Ret, typename F, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(F::*) (Arg, Rest...) const);

template <typename F>
decltype(first_argument_helper(&F::operator())) first_argument_helper(F);

template <typename T>
using first_argument = decltype(first_argument_helper(std::declval<T>()));

std::variant<int, std::string> data="abc";
template <typename V>
void Visit(V v)
using Arg1 = typename std::remove_const_t<std::remove_reference_t<first_argument<V>>>;//... TMP magic to get 1st argument of visitor + remove cvr, see Q 43526647
if (! std::holds_alternative<Arg1>(data))
std::cerr<< "alternative mismatchn";
return;

v(std::get<Arg1>(data));

int main()
Visit([](const int& i)std::cout << i << "n"; );
Visit([](const std::string& s)std::cout << s << "n"; );
// Visit([](auto& x)); ugly kabooom



This works, but it explodes with a user unfriendly compile time error when users passes a generic (e.g. [](auto&)) lambda. Is there a way to detect this and give nice static_assert() about it?
Would also be nice if it worked with function templates as well, not just with lambdas.



Note that I do not know what possible lambdas do, so I can not do some clever stuff with Dummy types since lambdas may invoke arbitrary functions on types.
In other words I can not try to call lambda in 2 std::void_t tests on int and std::string and if it works assume it is generic because they might try to call .BlaLol() on int and string.










share|improve this question



















  • 1





    What if the functor has an overloaded operator()? Visiting is also very commonly performed with overloaded functors (see example 4 here), do those have to be forbidden (or have to work)?

    – Max Langhof
    2 days ago












  • I think that is too hard to handle, but if it can be done that would be nice... so it is optional, not required.

    – NoSenseEtAl
    2 days ago













10












10








10


2






I implemented a Visit function (on a variant) that checks that the currently active type in the variant matches the function signature (more precisely the first argument). Based on this nice answer.
For example



#include <variant>
#include <string>
#include <iostream>

template<typename Ret, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(*) (Arg, Rest...));

template<typename Ret, typename F, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(F::*) (Arg, Rest...));

template<typename Ret, typename F, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(F::*) (Arg, Rest...) const);

template <typename F>
decltype(first_argument_helper(&F::operator())) first_argument_helper(F);

template <typename T>
using first_argument = decltype(first_argument_helper(std::declval<T>()));

std::variant<int, std::string> data="abc";
template <typename V>
void Visit(V v)
using Arg1 = typename std::remove_const_t<std::remove_reference_t<first_argument<V>>>;//... TMP magic to get 1st argument of visitor + remove cvr, see Q 43526647
if (! std::holds_alternative<Arg1>(data))
std::cerr<< "alternative mismatchn";
return;

v(std::get<Arg1>(data));

int main()
Visit([](const int& i)std::cout << i << "n"; );
Visit([](const std::string& s)std::cout << s << "n"; );
// Visit([](auto& x)); ugly kabooom



This works, but it explodes with a user unfriendly compile time error when users passes a generic (e.g. [](auto&)) lambda. Is there a way to detect this and give nice static_assert() about it?
Would also be nice if it worked with function templates as well, not just with lambdas.



Note that I do not know what possible lambdas do, so I can not do some clever stuff with Dummy types since lambdas may invoke arbitrary functions on types.
In other words I can not try to call lambda in 2 std::void_t tests on int and std::string and if it works assume it is generic because they might try to call .BlaLol() on int and string.










share|improve this question
















I implemented a Visit function (on a variant) that checks that the currently active type in the variant matches the function signature (more precisely the first argument). Based on this nice answer.
For example



#include <variant>
#include <string>
#include <iostream>

template<typename Ret, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(*) (Arg, Rest...));

template<typename Ret, typename F, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(F::*) (Arg, Rest...));

template<typename Ret, typename F, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(F::*) (Arg, Rest...) const);

template <typename F>
decltype(first_argument_helper(&F::operator())) first_argument_helper(F);

template <typename T>
using first_argument = decltype(first_argument_helper(std::declval<T>()));

std::variant<int, std::string> data="abc";
template <typename V>
void Visit(V v)
using Arg1 = typename std::remove_const_t<std::remove_reference_t<first_argument<V>>>;//... TMP magic to get 1st argument of visitor + remove cvr, see Q 43526647
if (! std::holds_alternative<Arg1>(data))
std::cerr<< "alternative mismatchn";
return;

v(std::get<Arg1>(data));

int main()
Visit([](const int& i)std::cout << i << "n"; );
Visit([](const std::string& s)std::cout << s << "n"; );
// Visit([](auto& x)); ugly kabooom



This works, but it explodes with a user unfriendly compile time error when users passes a generic (e.g. [](auto&)) lambda. Is there a way to detect this and give nice static_assert() about it?
Would also be nice if it worked with function templates as well, not just with lambdas.



Note that I do not know what possible lambdas do, so I can not do some clever stuff with Dummy types since lambdas may invoke arbitrary functions on types.
In other words I can not try to call lambda in 2 std::void_t tests on int and std::string and if it works assume it is generic because they might try to call .BlaLol() on int and string.







c++ c++17 variadic-templates template-meta-programming generic-lambda






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 2 days ago









max66

38.9k74574




38.9k74574










asked 2 days ago









NoSenseEtAlNoSenseEtAl

7,7031677184




7,7031677184







  • 1





    What if the functor has an overloaded operator()? Visiting is also very commonly performed with overloaded functors (see example 4 here), do those have to be forbidden (or have to work)?

    – Max Langhof
    2 days ago












  • I think that is too hard to handle, but if it can be done that would be nice... so it is optional, not required.

    – NoSenseEtAl
    2 days ago












  • 1





    What if the functor has an overloaded operator()? Visiting is also very commonly performed with overloaded functors (see example 4 here), do those have to be forbidden (or have to work)?

    – Max Langhof
    2 days ago












  • I think that is too hard to handle, but if it can be done that would be nice... so it is optional, not required.

    – NoSenseEtAl
    2 days ago







1




1





What if the functor has an overloaded operator()? Visiting is also very commonly performed with overloaded functors (see example 4 here), do those have to be forbidden (or have to work)?

– Max Langhof
2 days ago






What if the functor has an overloaded operator()? Visiting is also very commonly performed with overloaded functors (see example 4 here), do those have to be forbidden (or have to work)?

– Max Langhof
2 days ago














I think that is too hard to handle, but if it can be done that would be nice... so it is optional, not required.

– NoSenseEtAl
2 days ago





I think that is too hard to handle, but if it can be done that would be nice... so it is optional, not required.

– NoSenseEtAl
2 days ago












3 Answers
3






active

oldest

votes


















11















Is there a way to detect this and give nice static_assert about it?




I suppose you can use SFINAE over operator() type.



Follows an example



#include <type_traits>

template <typename T>
constexpr auto foo (T const &)
-> decltype( &T::operator(), bool )
return true;

constexpr bool foo (...)
return false;

int main()

auto l1 = [](int) return 0; ;
auto l2 = [](auto) return 0; ;

static_assert( foo(l1), "!" );
static_assert( ! foo(l2), "!" );



Instead of a bool, you can return std::true_type (from foo() first version) or std::false_type (from second version) if you want to use it through decltype().




Would also be nice if it worked with function templates as well, not just with lambdas.




I don't think it's possible in a so simple way: a lambda (also a generic lambda) is an object; a template function isn't an object but a set of objects. You can pass an object to a function, not a set of objects.



But the preceding solution should works also for classes/structs with operator()s: when there is a single, non template, operator(), you should get 1 from foo(); otherwise (no operator(), more than one operator(), template operator()), foo() should return 0.






share|improve this answer




















  • 2





    Trying to take the address of operator() was my initial idea as well (hence the comment) but then I somehow got lost in SFINAE on actually calling it. Anyway, here are some extra test cases involving overloaded functors: godbolt.org/z/M319jo

    – Max Langhof
    2 days ago



















4














Yet another simpler option:



#include <type_traits>
...
template <typename V>
void Visit(V v)
class Auto ;
static_assert(!std::is_invocable<V, Auto&>::value);
static_assert(!std::is_invocable<V, Auto*>::value);
...



The Auto class is just an invented type impossible to occur in the V parameters. If V accepts Auto as an argument it must be a generic.



I tested in coliru and I can confirm the solution covers these cases:



Visit([](auto x)); // nice static assert
Visit([](auto *x)); // nice static assert
Visit([](auto &x)); // nice static assert
Visit([](auto &&x)); // nice static assert


I'm not sure if that would cover all the possible lambdas that you don't know which are :)






share|improve this answer

























  • Nice idea ! You may ensure that "Auto" is unique like that : auto a_lambda = [](); using Auto= decltype(a_lambda);

    – Martin m
    2 days ago












  • @Martinm This seems to be the idiomatic way but does it actually have an advantage over the code in this answer?

    – Konrad Rudolph
    2 days ago











  • Well, I am not sure what happens in the case where an "Auto" class already define somewhere else. In meta-programming context I prefer to be sure that my type cannot be in conflict in some obscure case.

    – Martin m
    2 days ago






  • 4





    This gives both false positives (e.g. Visit([](std::any));) and false negatives (Visit([](int, auto)); or Visit([](auto*));)

    – Barry
    2 days ago












  • Visit([](int, auto)) is not a valid case because of v(std::get<Arg1>(data)); and Visit([](auto*)); is fixed now. I'm not sure if Visit([](std::any)) is one of the cases to be avoided as the question isn't clear enough.

    – olivecoder
    2 days ago



















3














#include <variant>
#include <string>
#include <iostream>

template <class U, typename T = void>
struct can_be_checked : public std::false_type ;

template <typename U>
struct can_be_checked<U, std::enable_if_t< std::is_function<U>::value > > : public std::true_type;

template <typename U>
struct can_be_checked<U, std::void_t<decltype(&U::operator())>> : public std::true_type;


template<typename Ret, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(*) (Arg, Rest...));

template<typename Ret, typename F, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(F::*) (Arg, Rest...));

template<typename Ret, typename F, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(F::*) (Arg, Rest...) const);

template <typename F>
decltype(first_argument_helper(&F::operator())) first_argument_helper(F);

template <typename T>
using first_argument = decltype(first_argument_helper(std::declval<T>()));

std::variant<int, std::string> data="abc";


template <typename V>
void Visit(V v)
if constexpr ( can_be_checked<std::remove_pointer_t<decltype(v)>>::value )

using Arg1 = typename std::remove_const_t<std::remove_reference_t<first_argument<V>>>;//... TMP magic to get 1st argument of visitor + remove cvr, see Q 43526647
if (! std::holds_alternative<Arg1>(data))

std::cerr<< "alternative mismatchn";
return;

v(std::get<Arg1>(data));

else

std::cout << "it's a template / auto lambda " << std::endl;





template <class T>
void foo(const T& t)

std::cout <<t << " foo n";


void fooi(const int& t)

std::cout <<t << " fooi " << std::endl;


int main()
Visit([](const int& i)std::cout << i << std::endl; );
Visit([](const std::string& s)std::cout << s << std::endl; );
Visit([](auto& x)std::cout <<x << std::endl;); // it's a template / auto lambda*/
Visit(foo<int>);

Visit<decltype(fooi)>(fooi);
Visit(fooi);


// Visit(foo); // => fail ugly



I don't know if it's you want, but you can, with that static_assert if an auto lambda is passed as parameter.



I think it's not possible to do the same for template function, but not sure.






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55488333%2fis-it-possible-to-static-assert-that-a-lambda-is-not-generic%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    11















    Is there a way to detect this and give nice static_assert about it?




    I suppose you can use SFINAE over operator() type.



    Follows an example



    #include <type_traits>

    template <typename T>
    constexpr auto foo (T const &)
    -> decltype( &T::operator(), bool )
    return true;

    constexpr bool foo (...)
    return false;

    int main()

    auto l1 = [](int) return 0; ;
    auto l2 = [](auto) return 0; ;

    static_assert( foo(l1), "!" );
    static_assert( ! foo(l2), "!" );



    Instead of a bool, you can return std::true_type (from foo() first version) or std::false_type (from second version) if you want to use it through decltype().




    Would also be nice if it worked with function templates as well, not just with lambdas.




    I don't think it's possible in a so simple way: a lambda (also a generic lambda) is an object; a template function isn't an object but a set of objects. You can pass an object to a function, not a set of objects.



    But the preceding solution should works also for classes/structs with operator()s: when there is a single, non template, operator(), you should get 1 from foo(); otherwise (no operator(), more than one operator(), template operator()), foo() should return 0.






    share|improve this answer




















    • 2





      Trying to take the address of operator() was my initial idea as well (hence the comment) but then I somehow got lost in SFINAE on actually calling it. Anyway, here are some extra test cases involving overloaded functors: godbolt.org/z/M319jo

      – Max Langhof
      2 days ago
















    11















    Is there a way to detect this and give nice static_assert about it?




    I suppose you can use SFINAE over operator() type.



    Follows an example



    #include <type_traits>

    template <typename T>
    constexpr auto foo (T const &)
    -> decltype( &T::operator(), bool )
    return true;

    constexpr bool foo (...)
    return false;

    int main()

    auto l1 = [](int) return 0; ;
    auto l2 = [](auto) return 0; ;

    static_assert( foo(l1), "!" );
    static_assert( ! foo(l2), "!" );



    Instead of a bool, you can return std::true_type (from foo() first version) or std::false_type (from second version) if you want to use it through decltype().




    Would also be nice if it worked with function templates as well, not just with lambdas.




    I don't think it's possible in a so simple way: a lambda (also a generic lambda) is an object; a template function isn't an object but a set of objects. You can pass an object to a function, not a set of objects.



    But the preceding solution should works also for classes/structs with operator()s: when there is a single, non template, operator(), you should get 1 from foo(); otherwise (no operator(), more than one operator(), template operator()), foo() should return 0.






    share|improve this answer




















    • 2





      Trying to take the address of operator() was my initial idea as well (hence the comment) but then I somehow got lost in SFINAE on actually calling it. Anyway, here are some extra test cases involving overloaded functors: godbolt.org/z/M319jo

      – Max Langhof
      2 days ago














    11












    11








    11








    Is there a way to detect this and give nice static_assert about it?




    I suppose you can use SFINAE over operator() type.



    Follows an example



    #include <type_traits>

    template <typename T>
    constexpr auto foo (T const &)
    -> decltype( &T::operator(), bool )
    return true;

    constexpr bool foo (...)
    return false;

    int main()

    auto l1 = [](int) return 0; ;
    auto l2 = [](auto) return 0; ;

    static_assert( foo(l1), "!" );
    static_assert( ! foo(l2), "!" );



    Instead of a bool, you can return std::true_type (from foo() first version) or std::false_type (from second version) if you want to use it through decltype().




    Would also be nice if it worked with function templates as well, not just with lambdas.




    I don't think it's possible in a so simple way: a lambda (also a generic lambda) is an object; a template function isn't an object but a set of objects. You can pass an object to a function, not a set of objects.



    But the preceding solution should works also for classes/structs with operator()s: when there is a single, non template, operator(), you should get 1 from foo(); otherwise (no operator(), more than one operator(), template operator()), foo() should return 0.






    share|improve this answer
















    Is there a way to detect this and give nice static_assert about it?




    I suppose you can use SFINAE over operator() type.



    Follows an example



    #include <type_traits>

    template <typename T>
    constexpr auto foo (T const &)
    -> decltype( &T::operator(), bool )
    return true;

    constexpr bool foo (...)
    return false;

    int main()

    auto l1 = [](int) return 0; ;
    auto l2 = [](auto) return 0; ;

    static_assert( foo(l1), "!" );
    static_assert( ! foo(l2), "!" );



    Instead of a bool, you can return std::true_type (from foo() first version) or std::false_type (from second version) if you want to use it through decltype().




    Would also be nice if it worked with function templates as well, not just with lambdas.




    I don't think it's possible in a so simple way: a lambda (also a generic lambda) is an object; a template function isn't an object but a set of objects. You can pass an object to a function, not a set of objects.



    But the preceding solution should works also for classes/structs with operator()s: when there is a single, non template, operator(), you should get 1 from foo(); otherwise (no operator(), more than one operator(), template operator()), foo() should return 0.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 2 days ago

























    answered 2 days ago









    max66max66

    38.9k74574




    38.9k74574







    • 2





      Trying to take the address of operator() was my initial idea as well (hence the comment) but then I somehow got lost in SFINAE on actually calling it. Anyway, here are some extra test cases involving overloaded functors: godbolt.org/z/M319jo

      – Max Langhof
      2 days ago













    • 2





      Trying to take the address of operator() was my initial idea as well (hence the comment) but then I somehow got lost in SFINAE on actually calling it. Anyway, here are some extra test cases involving overloaded functors: godbolt.org/z/M319jo

      – Max Langhof
      2 days ago








    2




    2





    Trying to take the address of operator() was my initial idea as well (hence the comment) but then I somehow got lost in SFINAE on actually calling it. Anyway, here are some extra test cases involving overloaded functors: godbolt.org/z/M319jo

    – Max Langhof
    2 days ago






    Trying to take the address of operator() was my initial idea as well (hence the comment) but then I somehow got lost in SFINAE on actually calling it. Anyway, here are some extra test cases involving overloaded functors: godbolt.org/z/M319jo

    – Max Langhof
    2 days ago














    4














    Yet another simpler option:



    #include <type_traits>
    ...
    template <typename V>
    void Visit(V v)
    class Auto ;
    static_assert(!std::is_invocable<V, Auto&>::value);
    static_assert(!std::is_invocable<V, Auto*>::value);
    ...



    The Auto class is just an invented type impossible to occur in the V parameters. If V accepts Auto as an argument it must be a generic.



    I tested in coliru and I can confirm the solution covers these cases:



    Visit([](auto x)); // nice static assert
    Visit([](auto *x)); // nice static assert
    Visit([](auto &x)); // nice static assert
    Visit([](auto &&x)); // nice static assert


    I'm not sure if that would cover all the possible lambdas that you don't know which are :)






    share|improve this answer

























    • Nice idea ! You may ensure that "Auto" is unique like that : auto a_lambda = [](); using Auto= decltype(a_lambda);

      – Martin m
      2 days ago












    • @Martinm This seems to be the idiomatic way but does it actually have an advantage over the code in this answer?

      – Konrad Rudolph
      2 days ago











    • Well, I am not sure what happens in the case where an "Auto" class already define somewhere else. In meta-programming context I prefer to be sure that my type cannot be in conflict in some obscure case.

      – Martin m
      2 days ago






    • 4





      This gives both false positives (e.g. Visit([](std::any));) and false negatives (Visit([](int, auto)); or Visit([](auto*));)

      – Barry
      2 days ago












    • Visit([](int, auto)) is not a valid case because of v(std::get<Arg1>(data)); and Visit([](auto*)); is fixed now. I'm not sure if Visit([](std::any)) is one of the cases to be avoided as the question isn't clear enough.

      – olivecoder
      2 days ago
















    4














    Yet another simpler option:



    #include <type_traits>
    ...
    template <typename V>
    void Visit(V v)
    class Auto ;
    static_assert(!std::is_invocable<V, Auto&>::value);
    static_assert(!std::is_invocable<V, Auto*>::value);
    ...



    The Auto class is just an invented type impossible to occur in the V parameters. If V accepts Auto as an argument it must be a generic.



    I tested in coliru and I can confirm the solution covers these cases:



    Visit([](auto x)); // nice static assert
    Visit([](auto *x)); // nice static assert
    Visit([](auto &x)); // nice static assert
    Visit([](auto &&x)); // nice static assert


    I'm not sure if that would cover all the possible lambdas that you don't know which are :)






    share|improve this answer

























    • Nice idea ! You may ensure that "Auto" is unique like that : auto a_lambda = [](); using Auto= decltype(a_lambda);

      – Martin m
      2 days ago












    • @Martinm This seems to be the idiomatic way but does it actually have an advantage over the code in this answer?

      – Konrad Rudolph
      2 days ago











    • Well, I am not sure what happens in the case where an "Auto" class already define somewhere else. In meta-programming context I prefer to be sure that my type cannot be in conflict in some obscure case.

      – Martin m
      2 days ago






    • 4





      This gives both false positives (e.g. Visit([](std::any));) and false negatives (Visit([](int, auto)); or Visit([](auto*));)

      – Barry
      2 days ago












    • Visit([](int, auto)) is not a valid case because of v(std::get<Arg1>(data)); and Visit([](auto*)); is fixed now. I'm not sure if Visit([](std::any)) is one of the cases to be avoided as the question isn't clear enough.

      – olivecoder
      2 days ago














    4












    4








    4







    Yet another simpler option:



    #include <type_traits>
    ...
    template <typename V>
    void Visit(V v)
    class Auto ;
    static_assert(!std::is_invocable<V, Auto&>::value);
    static_assert(!std::is_invocable<V, Auto*>::value);
    ...



    The Auto class is just an invented type impossible to occur in the V parameters. If V accepts Auto as an argument it must be a generic.



    I tested in coliru and I can confirm the solution covers these cases:



    Visit([](auto x)); // nice static assert
    Visit([](auto *x)); // nice static assert
    Visit([](auto &x)); // nice static assert
    Visit([](auto &&x)); // nice static assert


    I'm not sure if that would cover all the possible lambdas that you don't know which are :)






    share|improve this answer















    Yet another simpler option:



    #include <type_traits>
    ...
    template <typename V>
    void Visit(V v)
    class Auto ;
    static_assert(!std::is_invocable<V, Auto&>::value);
    static_assert(!std::is_invocable<V, Auto*>::value);
    ...



    The Auto class is just an invented type impossible to occur in the V parameters. If V accepts Auto as an argument it must be a generic.



    I tested in coliru and I can confirm the solution covers these cases:



    Visit([](auto x)); // nice static assert
    Visit([](auto *x)); // nice static assert
    Visit([](auto &x)); // nice static assert
    Visit([](auto &&x)); // nice static assert


    I'm not sure if that would cover all the possible lambdas that you don't know which are :)







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 2 days ago

























    answered 2 days ago









    olivecoderolivecoder

    2,0781216




    2,0781216












    • Nice idea ! You may ensure that "Auto" is unique like that : auto a_lambda = [](); using Auto= decltype(a_lambda);

      – Martin m
      2 days ago












    • @Martinm This seems to be the idiomatic way but does it actually have an advantage over the code in this answer?

      – Konrad Rudolph
      2 days ago











    • Well, I am not sure what happens in the case where an "Auto" class already define somewhere else. In meta-programming context I prefer to be sure that my type cannot be in conflict in some obscure case.

      – Martin m
      2 days ago






    • 4





      This gives both false positives (e.g. Visit([](std::any));) and false negatives (Visit([](int, auto)); or Visit([](auto*));)

      – Barry
      2 days ago












    • Visit([](int, auto)) is not a valid case because of v(std::get<Arg1>(data)); and Visit([](auto*)); is fixed now. I'm not sure if Visit([](std::any)) is one of the cases to be avoided as the question isn't clear enough.

      – olivecoder
      2 days ago


















    • Nice idea ! You may ensure that "Auto" is unique like that : auto a_lambda = [](); using Auto= decltype(a_lambda);

      – Martin m
      2 days ago












    • @Martinm This seems to be the idiomatic way but does it actually have an advantage over the code in this answer?

      – Konrad Rudolph
      2 days ago











    • Well, I am not sure what happens in the case where an "Auto" class already define somewhere else. In meta-programming context I prefer to be sure that my type cannot be in conflict in some obscure case.

      – Martin m
      2 days ago






    • 4





      This gives both false positives (e.g. Visit([](std::any));) and false negatives (Visit([](int, auto)); or Visit([](auto*));)

      – Barry
      2 days ago












    • Visit([](int, auto)) is not a valid case because of v(std::get<Arg1>(data)); and Visit([](auto*)); is fixed now. I'm not sure if Visit([](std::any)) is one of the cases to be avoided as the question isn't clear enough.

      – olivecoder
      2 days ago

















    Nice idea ! You may ensure that "Auto" is unique like that : auto a_lambda = [](); using Auto= decltype(a_lambda);

    – Martin m
    2 days ago






    Nice idea ! You may ensure that "Auto" is unique like that : auto a_lambda = [](); using Auto= decltype(a_lambda);

    – Martin m
    2 days ago














    @Martinm This seems to be the idiomatic way but does it actually have an advantage over the code in this answer?

    – Konrad Rudolph
    2 days ago





    @Martinm This seems to be the idiomatic way but does it actually have an advantage over the code in this answer?

    – Konrad Rudolph
    2 days ago













    Well, I am not sure what happens in the case where an "Auto" class already define somewhere else. In meta-programming context I prefer to be sure that my type cannot be in conflict in some obscure case.

    – Martin m
    2 days ago





    Well, I am not sure what happens in the case where an "Auto" class already define somewhere else. In meta-programming context I prefer to be sure that my type cannot be in conflict in some obscure case.

    – Martin m
    2 days ago




    4




    4





    This gives both false positives (e.g. Visit([](std::any));) and false negatives (Visit([](int, auto)); or Visit([](auto*));)

    – Barry
    2 days ago






    This gives both false positives (e.g. Visit([](std::any));) and false negatives (Visit([](int, auto)); or Visit([](auto*));)

    – Barry
    2 days ago














    Visit([](int, auto)) is not a valid case because of v(std::get<Arg1>(data)); and Visit([](auto*)); is fixed now. I'm not sure if Visit([](std::any)) is one of the cases to be avoided as the question isn't clear enough.

    – olivecoder
    2 days ago






    Visit([](int, auto)) is not a valid case because of v(std::get<Arg1>(data)); and Visit([](auto*)); is fixed now. I'm not sure if Visit([](std::any)) is one of the cases to be avoided as the question isn't clear enough.

    – olivecoder
    2 days ago












    3














    #include <variant>
    #include <string>
    #include <iostream>

    template <class U, typename T = void>
    struct can_be_checked : public std::false_type ;

    template <typename U>
    struct can_be_checked<U, std::enable_if_t< std::is_function<U>::value > > : public std::true_type;

    template <typename U>
    struct can_be_checked<U, std::void_t<decltype(&U::operator())>> : public std::true_type;


    template<typename Ret, typename Arg, typename... Rest>
    Arg first_argument_helper(Ret(*) (Arg, Rest...));

    template<typename Ret, typename F, typename Arg, typename... Rest>
    Arg first_argument_helper(Ret(F::*) (Arg, Rest...));

    template<typename Ret, typename F, typename Arg, typename... Rest>
    Arg first_argument_helper(Ret(F::*) (Arg, Rest...) const);

    template <typename F>
    decltype(first_argument_helper(&F::operator())) first_argument_helper(F);

    template <typename T>
    using first_argument = decltype(first_argument_helper(std::declval<T>()));

    std::variant<int, std::string> data="abc";


    template <typename V>
    void Visit(V v)
    if constexpr ( can_be_checked<std::remove_pointer_t<decltype(v)>>::value )

    using Arg1 = typename std::remove_const_t<std::remove_reference_t<first_argument<V>>>;//... TMP magic to get 1st argument of visitor + remove cvr, see Q 43526647
    if (! std::holds_alternative<Arg1>(data))

    std::cerr<< "alternative mismatchn";
    return;

    v(std::get<Arg1>(data));

    else

    std::cout << "it's a template / auto lambda " << std::endl;





    template <class T>
    void foo(const T& t)

    std::cout <<t << " foo n";


    void fooi(const int& t)

    std::cout <<t << " fooi " << std::endl;


    int main()
    Visit([](const int& i)std::cout << i << std::endl; );
    Visit([](const std::string& s)std::cout << s << std::endl; );
    Visit([](auto& x)std::cout <<x << std::endl;); // it's a template / auto lambda*/
    Visit(foo<int>);

    Visit<decltype(fooi)>(fooi);
    Visit(fooi);


    // Visit(foo); // => fail ugly



    I don't know if it's you want, but you can, with that static_assert if an auto lambda is passed as parameter.



    I think it's not possible to do the same for template function, but not sure.






    share|improve this answer



























      3














      #include <variant>
      #include <string>
      #include <iostream>

      template <class U, typename T = void>
      struct can_be_checked : public std::false_type ;

      template <typename U>
      struct can_be_checked<U, std::enable_if_t< std::is_function<U>::value > > : public std::true_type;

      template <typename U>
      struct can_be_checked<U, std::void_t<decltype(&U::operator())>> : public std::true_type;


      template<typename Ret, typename Arg, typename... Rest>
      Arg first_argument_helper(Ret(*) (Arg, Rest...));

      template<typename Ret, typename F, typename Arg, typename... Rest>
      Arg first_argument_helper(Ret(F::*) (Arg, Rest...));

      template<typename Ret, typename F, typename Arg, typename... Rest>
      Arg first_argument_helper(Ret(F::*) (Arg, Rest...) const);

      template <typename F>
      decltype(first_argument_helper(&F::operator())) first_argument_helper(F);

      template <typename T>
      using first_argument = decltype(first_argument_helper(std::declval<T>()));

      std::variant<int, std::string> data="abc";


      template <typename V>
      void Visit(V v)
      if constexpr ( can_be_checked<std::remove_pointer_t<decltype(v)>>::value )

      using Arg1 = typename std::remove_const_t<std::remove_reference_t<first_argument<V>>>;//... TMP magic to get 1st argument of visitor + remove cvr, see Q 43526647
      if (! std::holds_alternative<Arg1>(data))

      std::cerr<< "alternative mismatchn";
      return;

      v(std::get<Arg1>(data));

      else

      std::cout << "it's a template / auto lambda " << std::endl;





      template <class T>
      void foo(const T& t)

      std::cout <<t << " foo n";


      void fooi(const int& t)

      std::cout <<t << " fooi " << std::endl;


      int main()
      Visit([](const int& i)std::cout << i << std::endl; );
      Visit([](const std::string& s)std::cout << s << std::endl; );
      Visit([](auto& x)std::cout <<x << std::endl;); // it's a template / auto lambda*/
      Visit(foo<int>);

      Visit<decltype(fooi)>(fooi);
      Visit(fooi);


      // Visit(foo); // => fail ugly



      I don't know if it's you want, but you can, with that static_assert if an auto lambda is passed as parameter.



      I think it's not possible to do the same for template function, but not sure.






      share|improve this answer

























        3












        3








        3







        #include <variant>
        #include <string>
        #include <iostream>

        template <class U, typename T = void>
        struct can_be_checked : public std::false_type ;

        template <typename U>
        struct can_be_checked<U, std::enable_if_t< std::is_function<U>::value > > : public std::true_type;

        template <typename U>
        struct can_be_checked<U, std::void_t<decltype(&U::operator())>> : public std::true_type;


        template<typename Ret, typename Arg, typename... Rest>
        Arg first_argument_helper(Ret(*) (Arg, Rest...));

        template<typename Ret, typename F, typename Arg, typename... Rest>
        Arg first_argument_helper(Ret(F::*) (Arg, Rest...));

        template<typename Ret, typename F, typename Arg, typename... Rest>
        Arg first_argument_helper(Ret(F::*) (Arg, Rest...) const);

        template <typename F>
        decltype(first_argument_helper(&F::operator())) first_argument_helper(F);

        template <typename T>
        using first_argument = decltype(first_argument_helper(std::declval<T>()));

        std::variant<int, std::string> data="abc";


        template <typename V>
        void Visit(V v)
        if constexpr ( can_be_checked<std::remove_pointer_t<decltype(v)>>::value )

        using Arg1 = typename std::remove_const_t<std::remove_reference_t<first_argument<V>>>;//... TMP magic to get 1st argument of visitor + remove cvr, see Q 43526647
        if (! std::holds_alternative<Arg1>(data))

        std::cerr<< "alternative mismatchn";
        return;

        v(std::get<Arg1>(data));

        else

        std::cout << "it's a template / auto lambda " << std::endl;





        template <class T>
        void foo(const T& t)

        std::cout <<t << " foo n";


        void fooi(const int& t)

        std::cout <<t << " fooi " << std::endl;


        int main()
        Visit([](const int& i)std::cout << i << std::endl; );
        Visit([](const std::string& s)std::cout << s << std::endl; );
        Visit([](auto& x)std::cout <<x << std::endl;); // it's a template / auto lambda*/
        Visit(foo<int>);

        Visit<decltype(fooi)>(fooi);
        Visit(fooi);


        // Visit(foo); // => fail ugly



        I don't know if it's you want, but you can, with that static_assert if an auto lambda is passed as parameter.



        I think it's not possible to do the same for template function, but not sure.






        share|improve this answer













        #include <variant>
        #include <string>
        #include <iostream>

        template <class U, typename T = void>
        struct can_be_checked : public std::false_type ;

        template <typename U>
        struct can_be_checked<U, std::enable_if_t< std::is_function<U>::value > > : public std::true_type;

        template <typename U>
        struct can_be_checked<U, std::void_t<decltype(&U::operator())>> : public std::true_type;


        template<typename Ret, typename Arg, typename... Rest>
        Arg first_argument_helper(Ret(*) (Arg, Rest...));

        template<typename Ret, typename F, typename Arg, typename... Rest>
        Arg first_argument_helper(Ret(F::*) (Arg, Rest...));

        template<typename Ret, typename F, typename Arg, typename... Rest>
        Arg first_argument_helper(Ret(F::*) (Arg, Rest...) const);

        template <typename F>
        decltype(first_argument_helper(&F::operator())) first_argument_helper(F);

        template <typename T>
        using first_argument = decltype(first_argument_helper(std::declval<T>()));

        std::variant<int, std::string> data="abc";


        template <typename V>
        void Visit(V v)
        if constexpr ( can_be_checked<std::remove_pointer_t<decltype(v)>>::value )

        using Arg1 = typename std::remove_const_t<std::remove_reference_t<first_argument<V>>>;//... TMP magic to get 1st argument of visitor + remove cvr, see Q 43526647
        if (! std::holds_alternative<Arg1>(data))

        std::cerr<< "alternative mismatchn";
        return;

        v(std::get<Arg1>(data));

        else

        std::cout << "it's a template / auto lambda " << std::endl;





        template <class T>
        void foo(const T& t)

        std::cout <<t << " foo n";


        void fooi(const int& t)

        std::cout <<t << " fooi " << std::endl;


        int main()
        Visit([](const int& i)std::cout << i << std::endl; );
        Visit([](const std::string& s)std::cout << s << std::endl; );
        Visit([](auto& x)std::cout <<x << std::endl;); // it's a template / auto lambda*/
        Visit(foo<int>);

        Visit<decltype(fooi)>(fooi);
        Visit(fooi);


        // Visit(foo); // => fail ugly



        I don't know if it's you want, but you can, with that static_assert if an auto lambda is passed as parameter.



        I think it's not possible to do the same for template function, but not sure.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 2 days ago









        Martin mMartin m

        885




        885



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55488333%2fis-it-possible-to-static-assert-that-a-lambda-is-not-generic%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            getting Checkpoint VPN SSL Network Extender working in the command lineHow to connect to CheckPoint VPN on Ubuntu 18.04LTS?Will the Linux ( red-hat ) Open VPNC Client connect to checkpoint or nortel VPN gateways?VPN client for linux machine + support checkpoint gatewayVPN SSL Network Extender in FirefoxLinux Checkpoint SNX tool configuration issuesCheck Point - Connect under Linux - snx + OTPSNX VPN Ububuntu 18.XXUsing Checkpoint VPN SSL Network Extender CLI with certificateVPN with network manager (nm-applet) is not workingWill the Linux ( red-hat ) Open VPNC Client connect to checkpoint or nortel VPN gateways?VPN client for linux machine + support checkpoint gatewayImport VPN config files to NetworkManager from command lineTrouble connecting to VPN using network-manager, while command line worksStart a VPN connection with PPTP protocol on command linestarting a docker service daemon breaks the vpn networkCan't connect to vpn with Network-managerVPN SSL Network Extender in FirefoxUsing Checkpoint VPN SSL Network Extender CLI with certificate

            Cannot Extend partition with GParted The 2019 Stack Overflow Developer Survey Results Are In Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern) 2019 Community Moderator Election ResultsCan't increase partition size with GParted?GParted doesn't recognize the unallocated space after my current partitionWhat is the best way to add unallocated space located before to Ubuntu 12.04 partition with GParted live?I can't figure out how to extend my Arch home partition into free spaceGparted Linux Mint 18.1 issueTrying to extend but swap partition is showing as Unknown in Gparted, shows proper from fdiskRearrange partitions in gparted to extend a partitionUnable to extend partition even though unallocated space is next to it using GPartedAllocate free space to root partitiongparted: how to merge unallocated space with a partition

            NetworkManager fails with “Could not find source connection”Trouble connecting to VPN using network-manager, while command line worksHow can I be notified about state changes to a VPN adapterBacktrack 5 R3 - Refuses to connect to VPNFeed all traffic through OpenVPN for a specific network namespace onlyRun daemon on startup in Debian once openvpn connection establishedpfsense tcp connection between openvpn and lan is brokenInternet connection problem with web browsers onlyWhy does NetworkManager explicitly support tun/tap devices?Browser issues with VPNTwo IP addresses assigned to the same network card - OpenVPN issues?Cannot connect to WiFi with nmcli, although secrets are provided